简体   繁体   English

在 jpa 中保存 object 之前,我如何知道 id

[英]How do I know the id before saving an object in jpa

I have a new object. I want to know id before saving it.我有一个新的 object。我想在保存之前知道它的 ID。 Is it possible?是否可以? Or there is another way for this?或者还有另一种方法吗? I am using jpa as orm and oracle as database.我使用 jpa 作为 orm 和 oracle 作为数据库。

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

I have a code field in my entity.我的实体中有一个代码字段。 If the user doesn't enter a value for the code field, I want to set code as entity's id.如果用户没有为code字段输入值,我想将代码设置为实体的 ID。 If I persist entity, of course i can get id and set code value as id, but this is extra query database.如果我持久化实体,当然我可以获得 id 并将代码值设置为 id,但这是额外的查询数据库。

I want to do something like that我想做那样的事

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

After long researching about this, finally I found a solution. 经过长时间的研究,终于找到了解决方案。

In fact, if you use sequence generator in jpa, certainly you cannot obtain entity's id before saving it in database, because next id will be assigned by database sequence. 实际上,如果在jpa中使用序列生成器 ,则肯定无法在将实体的ID保存到数据库之前获取实体的ID,因为下一个ID将由数据库序列分配。

There is one way to obtain the id if you use a custom generator , you can get the id before saving. 如果使用自定义生成器 ,则有一种获取ID的方法,可以在保存之前获取ID。 Here is simple implementation: 这是简单的实现:

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);
    }
}

Using CustomGenerator for id field: 使用CustomGenerator for 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;

With a @GeneratedValue type id you can't know that value in advance (before actually writing it). 使用@GeneratedValue类型id时,您无法事先知道该值(在实际写入之前)。 However once you persist your Bean, the id field will be populated in that bean instance and you can obtain it without needing to do an extra query for it. 但是,一旦持久化Bean,则将在该Bean实例中填充id字段,而无需对其进行额外查询即可获取它。 In other words: 换一种说法:

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();

Also, depending on how your EntityManager is configured, you might need to also first commit the transaction (manually) before you can get that id. 另外,根据EntityManager的配置方式,您可能还需要先(手动)提交事务,然后才能获取该ID。

Update as per comment 根据评论更新

If you want to intercept and do something to the entity before it is saved and/or updated, you can use JPA LifeCycle Listeners (if you're using JPA version 2): Handling JPA lifecycle event using listeners and callbacks . 如果要在保存和/或更新实体之前对其进行拦截并对其执行某些操作,则可以使用JPA LifeCycle侦听器(如果使用的是JPA版本2): 使用侦听器和回调处理JPA生命周期事件

Basically you can make a validate() method in your bean, annotate it with @PrePersist and @PreUpdate and do the validation in it (if code is empty set it to id's value) 基本上,您可以在bean中创建一个validate()方法,用@PrePersist@PreUpdate对其进行注释,然后在其中进行验证(如果代码为空,则将其设置为id的值)

Update per 2nd comment 每2条评论的更新

Yes, I honestly just thought of that just now: that if the id is auto generated, it might get populated AFTER the pre-persist event, such that when your pre-persist code is executed you still don't know what the id is (you may notice also that in the example you link to the id is NOT autogenerated but set manually). 是的,老实说,我刚才想到的是:如果id是自动生成的,则可能在pre-persist事件发生后填充它,这样,当执行pre-persist代码时,您仍然不知道id是什么(您可能还会注意到,在示例中,您链接到ID的链接不是自动生成的,而是手动设置的)。 What you can do in this case is add a boolean field to your entity (annotated with @Transient so it won't get persisted) called isCodeEmpty (which is false by default if not specifically initialized). 在这种情况下,您可以做的是向您的实体添加一个布尔字段(用@Transient注释,这样它就不会持久化),称为isCodeEmpty (如果未特别初始化,默认情况下为false)。 Then in your @PrePersist annotated method you check if the value for code field is empty and if so, set the boolean to true. 然后在@PrePersist注释的方法中,检查code字段的值是否为空,如果为空,则将boolean设置为true。 Then you refactor your setId(...) method such that (aside from setting the id field) it will check this boolean, and if true set the value of the code field to that of the id field: 然后,重构setId(...)方法,以便(除了设置id字段之外)将检查此布尔值,如果为true,则将代码字段的值设置为id字段的值:

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;
 }

}


}

Here is the solution that works for me:这是对我有用的解决方案:

    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "my_seq" )
    @SequenceGenerator( name = "my_seq", sequenceName = "my_seq" )
    @Access( AccessType.PROPERTY )
    private Long id;

    @Column( name = "CODE", nullable = false, updatable = false )
    private Long code;

    public void setId(Long id) {
        this.id = id;
        if (code == null) {
            code = id;
        }
    }

The important part is placing the @javax.persistence.Access( AccessType.PROPERTY ) annotation, which makes Hibernate use the getter and the setter to access the id field.重要的部分是放置@javax.persistence.Access( AccessType.PROPERTY )注释,这使得 Hibernate 使用 getter 和 setter 来访问 id 字段。 Without it, when the @Id annotation placed directly on a field rather than on the field getter, Hibernate uses a field-based access strategy (getter and setter are not used).没有它,当@Id注解直接放在字段上而不是字段getter上时,Hibernate使用基于字段的访问策略(不使用getter和setter)。 Link: https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/domain/access.htmlhiber链接: https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/domain/access.htmlhiber

Just follow these steps then you will get the id before you complete the transaction 1st step adds an entity listener at your entity level by using the annotation called "@EntityListeners". 只需按照以下步骤操作,您将在完成事务之前获取ID。第一个步骤通过使用称为“ @EntityListeners”的注释在实体级别添加实体侦听器。

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

2nd step 第二步

public class SomeLinstener{

    @PostPersist
    public void userPostPersist(YourEntity obj) {

        try {
            obj.getId();
        }catch(Exception e) {

        }
    } 

this will you an id which has been generated by your generator and you can reuse where ever it is required this will give in a single transaction. 这将为您提供一个由生成器生成的ID,您可以在需要的任何地方重复使用,这将在一次交易中给出。

hope this will help for somebody else 希望这对其他人有帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在保存到数据库之前如何获取生成器ID? - How do I get the generator Id before saving to database? 如果我事先不知道其对象模型,该如何解析json的字符串? - How do I parse a string of json if I do not know its object model before hand? JPA-TransientPropertyValueException,而仅保存具有ID的对象 - JPA - TransientPropertyValueException while saving object with only ID 在知道构造函数的参数之前,如何初始化类对象? - how do i initialize class object before i know the arguments for constructor? JPA:如何避免加载对象,以便将其ID存储在数据库中? - JPA: How do I avoid loading an object simply so I can store its ID in the database? 如果我在解析之前不知道所有 Z466DEEC76ECDF2456D38571F6Z 字段,如何将 JSON 转换为 Java object? - How to convert JSON to Java object if I do not know all json fields before parsing? jpa - 在保存到存储库进行测试之前/之后覆盖 ID 自动生成? - jpa - Override Id Auto Generating before/after saving to repository for testing? 如何在JPA中查询组合对象? - How do I query an composed Object in JPA? 如何将具有复合ID的对象连接到具有复合ID但不具有相同复合ID的另一个对象上? (JPA批注) - How do you join an object with a composite id on another object with a composite id but not the same composite id? (JPA annotations) JPA:JPA 在搜索 id 之前修剪字符串 - JPA : Do JPA trims the string before it search for id
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM