我需要一些看似不那么具体的东西,但无论如何我都无法提出漂亮而复杂的解决方案。
说我有非常简单的hibernate / jpa实体:
@Entity(name="entity")
public class Type {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(unique = true, nullable = false)
private String name;
@Column(unique = false, nullable = false)
private boolean defaultType;
}
我需要的是以某种方式注释 defaultType 字段,因此只有(并且确切地说)一个持久化实体将此值设为true。当新实体持续使用此 defaultType 为true时,必须更改旧实体( defaultType = true)实体及其 defaultType 值改为假。此外,如果任何实体被更改(其 defaultType 已更改为true),则应适用相同的规则。
据我所知,这可以在业务逻辑内部实现(例如在DAO层),使用DB触发器或使用hibernates拦截器或事件(如果有其他方式,请告诉我)。我尝试使用DAO解决方案,但它是一种糟糕的解决方案,因为它可以被绕过,对于这种简单的操作来说真的很笨拙。数据库触发器无法添加hibernate / jpa注释(如果我没有记错),我不知道如何使用hibernate拦截器/事件来实现此功能。
那么,这个问题的最佳解决方案是什么?
答案 0 :(得分:1)
您需要在JPA中使用Callback方法,例如PreUpdate或PostUpdate,例如:
@Entity(name="entity")
@EntityListeners(com.yourpackage.TypeListner.class)
public class Type {
...
@Column(unique = false, nullable = false)
private boolean defaultType;
}
public class TypeListner {
pivate static Type objectWithTrue = null;
public void init() { // call this method when application is started
List<Type> results = entityManager
.createQuery("from Type", Type.class)
.getResultList();
for(Type type: results) {
if(type.getDefaultType()) {
objectWithTrue = type;
}
}
}
private void changeDefaultType(Type changed) {
if(changed.getDefaultType()) {
if(changed != objectWithTrue && objectWithTrue != null) {
objectWithTrue.setDefaultType(false);
}
objectWithTrue = changed;
}
}
@PostPresist
public void newType(Type changed) {
changeDefaultType(changed);
}
@PostUpdate
public void updateType(Type changed) {
changeDefaultType(changed);
}
@PreRemove
public void removeType(Type changed) {
if(changed.getDefaultType() && objectWithTrue == changed) {
objectWithTrue = null;
}
}
更新:关于您的问题,如果我找不到您想要的内容,此代码可能会对您有所帮助:
@PreUpdate
void updateType(Type changed) {
if(changed.getDefaultType()
List<Type> results = entityManager
.createQuery("from Type", Type.class)
.getResultList();
for(Type type: results) {
if(changed != type && type.getDefaultType()) {
type.setDefaultType(false);
}
}
}
}
或强>
您可以使用listner @PreUpdate和@PrePresist,并且每次覆盖所有Type对象而不存储任何变量(对于性能而言,这不是第一个示例,但更可靠):
class Lion extends Animal{
public Lion() {
super(new String[]{"steak", "celery"});
}
//...
}