使用JPA使实体成为只读的正确方法是什么?我希望我的数据库表永远不会以编程方式进行修改。
我想我明白我应该用LockModeType.READ
锁定我的对象。从数据库中检索后,是否可以使用注释使我的实体直接锁定?或者,我是否必须乱用并覆盖该特定实体的通用DAO?
答案 0 :(得分:44)
解决方案是使用基于字段的注释,将您的字段声明为protected
并仅建议公共getter。这样做,您的对象无法更改。
(此解决方案不是特定于实体的,它只是一种构建不可变对象的方法)
答案 1 :(得分:29)
您可以使用JPA生命周期监听器为您的实体创建防弹安全网。
在您的实体中添加EntityListener
,如下所示:
@Entity
@EntityListeners(PreventAnyUpdate.class)
public class YourEntity {
// ...
}
实施EntityListener
,如果发生任何更新,则抛出异常:
public class PreventAnyUpdate {
@PrePersist
void onPrePersist(Object o) {
throw new RuntimeException("...");
}
@PreUpdate
void onPreUpdate(Object o) {
throw new RuntimeException("...");
}
@PreRemove
void onPreRemove(Object o) {
throw new RuntimeException("...");
}
}
答案 2 :(得分:21)
如果你的JPA实现是休眠的 - 你可以使用hibernate Entity annotation
@org.hibernate.annotations.Entity(mutable = false)
显然,这会将你的模型与休眠联系起来。
答案 3 :(得分:18)
Hibernate还有一个org.hibernate.annotations.Immutable
注释,可以放在类型,方法或字段上。
答案 4 :(得分:13)
我认为你要找的是你的实体是不可变的。 Hibernate支持这个; JPA(至少JPA 1.0)没有。我想你只能通过提供getter来控制它,并确保getter只返回不可变的值。
答案 5 :(得分:11)
IIRC您可以在insertable = false
注释中将每个字段设置为updatable = false
和@Column
,但我确信必须有更好的方法......:)
我不认为this有帮助吗?
答案 6 :(得分:10)
Eclipselink实现还为您提供实体级{/ 1}}注释
答案 7 :(得分:6)
这可能会让我失望,因为我总是倾向于建议它,但您可以通过多种方式使用AspectJ来强制执行此操作:
自动化Mac的解决方案(使AspectJ注入@Column
注释):
declare @field : (@Entity *) *.* : @Column(insertable=false);
或者为所有对set方法的访问声明编译器错误:
declare error : execution((@Entity *) *.set*(*) );
,这很容易
答案 8 :(得分:3)
如果您正在使用spring-data或以其他方式使用Repository模式,请不要在该特定实体的Repository中包含任何save / update / create / insert / etc方法。这可以通过为只读实体提供基类/接口来推广,并且可以为可更新实体扩展可读的实体。正如其他海报所指出的那样,设置者也可能是非公开的,以避免开发人员意外设置他们无法保存的值。