我正在使用Spring Data JpaRepository
,Hibernate作为JPA提供程序。
通常直接使用Hibernate时,EntityManager#persist()
和EntityManager#save()
之间的决定取决于程序员。使用Spring Data存储库,只有save()
。我不想在这里讨论利弊。让我们考虑以下简单的基类:
@MappedSuperclass
public abstract class PersistableObject {
@Id
private String id;
public PersistableObject(){
this.id = UUID.randomUUID().toString();
}
// hashCode() and equals() are implemented based on equality of 'id'
}
使用此基类,Spring Data存储库无法分辨哪些实体是“新的”(尚未保存到DB),因为id == null
的常规检查在这种情况下显然不起作用,因为我们热切地指定UUID以确保equals()
和hashCode()
的正确性。所以存储库似乎总是调用EntityManager#merge()
- 这对于瞬态实体来说显然是低效的。
问题是:如何告诉JPA(或Spring数据)实体是新的,如果可能,它会使用EntityManager#persist()
代替#merge()
?< / p>
我正在思考这些问题(使用JPA生命周期回调):
@MappedSuperclass
public abstract class PersistableObject {
@Transient
private boolean isNew = true; // by default, treat entity as new
@PostLoad
private void loaded(){
// a loaded entity is never new
this.isNew = false;
}
@PostPersist
private void saved(){
// a saved entity is not new anymore
this.isNew = false;
}
// how do I get JPA (or Spring Data) to use this method?
public boolean isNew(){
return this.isNew;
}
// all other properties, constructor, hashCode() and equals same as above
}
答案 0 :(得分:5)
我想在这里再补充一句话。即使它仅适用于Spring Data而不适用于一般JPA,我认为值得一提的是Spring提供了Persistable <T>
接口,它有两种方法:
T getId();
boolean isNew();
通过实现此接口(例如在开放问题帖子中),Spring Data JpaRepositories将询问实体本身是否是新的,这在某些情况下非常方便。
答案 1 :(得分:4)
也许您应该添加@Version列:
@Version
private Long version
在新实体的情况下,它将为null