Java 有没有办法在HibernateInterceptor中为新实体实例获取生成的id? 为了讨论,考虑下面的Hibernate注释对象: @Entity public class TestModelObject { @Id @GeneratedValue @Column private int id; @Column private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Java 有没有办法在HibernateInterceptor中为新实体实例获取生成的id? 为了讨论,考虑下面的Hibernate注释对象: @Entity public class TestModelObject { @Id @GeneratedValue @Column private int id; @Column private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } },java,hibernate,Java,Hibernate,问题是,如何通过HibernateInterceptor(通过session.save保存)为新实例获取生成的ID值?我将概述我已经测试过的一些可用方法,并解释为什么每种方法都不够: -不工作,因为对于正在插入的新实例,id为null。这是有意义的,因为Hibernate在本例中不提前知道ID,因为它是由RDBMS在插入时生成的 -这有我要找的数据,但无法使用。它包含一个包含许多正在刷新的对象的迭代器,包括您感兴趣的对象,但是要从迭代器中拉出新保存的实例,没有一种简单的方法,不需要做一些非常粗

问题是,如何通过HibernateInterceptor(通过
session.save保存)为新实例获取生成的ID值?我将概述我已经测试过的一些可用方法,并解释为什么每种方法都不够:

  • -不工作,因为对于正在插入的新实例,id为null。这是有意义的,因为Hibernate在本例中不提前知道ID,因为它是由RDBMS在插入时生成的
  • -这有我要找的数据,但无法使用。它包含一个包含许多正在刷新的对象的迭代器,包括您感兴趣的对象,但是要从迭代器中拉出新保存的实例,没有一种简单的方法,不需要做一些非常粗俗的事情,比如添加一个“标记”布尔值并在onSave中填充它,然后在这里查找它
  • -此类具有数据,但无法使用。每次Hibernate实例化一个对象时都会调用它,并且它将id作为参数包含在内。它肯定会被一个新的持久化实体调用,但是没有理由与实体本身相关联,因为它只包括类名、类型(本例中为POJO)和id
我希望像
postSave
这样的东西会在插入完成后触发,对于新创建的实体,它会填充生成的id。但我没能找到这样的东西。有没有什么方法可以完成我想做的事情,而不必求助于黑客,比如保存两次,在第二次保存时执行拦截器“工作”?

你试过了吗?
使用实体监听器,您可以如下注释实体类:

@Entity
@EntityListeners({ UserEntityListener.class, UserPasswordValidator.class })
public class Book {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Columnt(name = "LOGIN")
    private String login;

    @Column(name = "PASSWORD")
    private String password;

    // getters, setters ommited

}
然后实现侦听器:

public class BookEntityListener {

    @PostPersist
    public void postPersist(User user) {
        // do your logic
    }

}

public class PasswordValidator {

    @PrePersist
    @PreUpdate
    public void validatePassword(User user) {
        if (passwordTooShort(user.password())
            throw new PersistenceException("Password too short");
    }

}
有多个生命周期注释可用:


  • 在实际执行实体管理器持久化操作之前执行 执行或级联。此调用与持久化操作同步


  • 在实体管理器持久化操作实际执行后执行,或 级联。此调用在执行数据库
    INSERT
    后调用


  • 在实际执行实体管理器删除操作之前执行;或 级联。此调用与删除操作同步


  • 在实体管理器删除操作实际完成后执行 执行或级联。此调用与remove同步 手术


  • 在数据库更新操作之前执行


  • 在数据库
    UPDATE
    操作后执行


  • 将实体加载到当前数据库后执行 已刷新持久性上下文或实体


你是否知道
@PostPersist
@PostUpdate
是否会对只有映射集合更改的实体开火?在这种情况下,没有调用where
onFlushDirty
,如果潜在问题也影响到实体侦听器,那么我就不能使用它们。如果你不知道,那么我可以测试它;谢谢。但是,如果您的子实体中映射了与父实体的
对一
关系,则您也可以侦听子实体,并通过从子实体调用来访问父实体。