在 jpa 中保存对象之前如何知道 id根据评论更新根据第二条评论进行更新

2022-09-02 20:57:25

我有一个新对象。我想知道id之前保存它。可能吗?还是有另一种方法?我使用jpa作为orm和oracle作为数据库。

@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq")
private Long id;

我的实体中有一个代码字段。如果用户没有为字段输入值,我想将代码设置为实体的 id。如果我坚持实体,我当然可以获取id并将代码值设置为id,但这是额外的查询数据库。code

我想做这样的事情

if(entity.getCode()==null) {
   entity.setCode(entity.getId);
   jpaDao.saveOrUpdate(entity);
}

答案 1

使用@GeneratedValue类型id,您无法提前知道该值(在实际写入之前)。但是,一旦您保留了Bean,id字段将填充在该Bean实例中,您可以获取它而无需对其进行额外的查询。换句话说:

MyEntiry myEnt = new MyEntity(); //the id field is null now
entityManager.persist(myEnt);//the id field is populated in myEnt now
Long id = myEnt.getId();

此外,根据配置的配置方式,您可能还需要先提交事务(手动),然后才能获取该 ID。EntityManager

根据评论更新

如果要在保存和/或更新实体之前对其进行拦截和执行某些操作,可以使用 JPA LifeCycle 侦听器(如果您使用的是 JPA 版本 2):使用侦听器和回调处理 JPA 生命周期事件

基本上,您可以在bean中创建一个方法,用它注释并在其中进行验证(如果代码为空,请将其设置为id的值)validate()@PrePersist@PreUpdate

根据第二条评论进行更新

是的,老实说,我刚才刚刚想到了这一点:如果id是自动生成的,它可能会在pre-persist事件之后被填充,这样当你的pre-persist代码被执行时,你仍然不知道id是什么(你可能还会注意到,在示例中,你链接到的id不是自动生成的,而是手动设置的)。在这种情况下,您可以做的是向实体添加一个布尔字段(注释为,因此它不会持久化)调用(如果未专门初始化,则默认为 false)。然后在带批注的方法中,检查代码字段的值为空,如果为空,请将布尔值设置为 true。然后,重构方法,以便(除了设置 id 字段之外)它将检查此布尔值,如果为 true,则将代码字段的值设置为 id 字段的值:@TransientisCodeEmpty@PrePersistsetId(...)

public class YourEntity {

@Transient
private boolean isCodeEmpty;

public void setId(Whatever id) {
 this.id = id;
 if(isCodeEmpty) {
  this.code = id;
  //if necessary:
  //this.isCodeEmpty = false;
 }
}

@PrePersist
public void validate() {
 if(code == null || code.isEmpty()) {
  isCodeEmpty = true;
 }

}


}

答案 2

经过长时间的研究,我终于找到了解决方案。

实际上,如果在 jpa 中使用序列生成器,当然在将实体 id 保存到数据库中之前无法获取实体 id,因为下一个 id 将由数据库序列分配。

如果使用自定义生成器,则有一种方法可以获取id,您可以在保存之前获取id。以下是简单的实现:

public class CustomGenerator extends IdentityGenerator implements Configurable {

    private IdentifierGenerator defaultGenerator;

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
        Long idValue = (Long)defaultGenerator.generate(session, object);
        //idValue will be assigned your entity id
        return idValue;
    }

    @Override
    public void configure(Type type, Properties params, Dialect d) throws MappingException {
        DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory();
        dd.setDialect(d);
        defaultGenerator = dd.createIdentifierGenerator("sequence", type, params);
    }
}

对 id 字段使用自定义生成器:

@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") })
@GeneratedValue(generator = "seq_id")
private Long id;

推荐