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; } }
问题是,如何通过HibernateInterceptor(通过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在插入时生成的 -这有我要找的数据,但无法使用。它包含一个包含许多正在刷新的对象的迭代器,包括您感兴趣的对象,但是要从迭代器中拉出新保存的实例,没有一种简单的方法,不需要做一些非常粗
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
是否会对只有映射集合更改的实体开火?在这种情况下,没有调用whereonFlushDirty
,如果潜在问题也影响到实体侦听器,那么我就不能使用它们。如果你不知道,那么我可以测试它;谢谢。但是,如果您的子实体中映射了与父实体的对一
关系,则您也可以侦听子实体,并通过从子实体调用来访问父实体。