What is the proper way to make an Entity read-only with JPA ? I wish my database table to never be modified at all programmatically.
使用JPA使实体只读的正确方法是什么?我希望我的数据库表永远不会以编程方式修改。
I think I understand that I should lock my objects with LockModeType.READ
. Is it possible to use an annotation to make my entities directly locked after retrieval from the database ? Or do I have to mess around and override my generic DAO for that specific entity ?
我想我理解我应该用lockmodetype来锁定我的对象。是否可以使用注释使我的实体在从数据库检索后直接锁定?或者,我是否需要将我的泛型DAO替换为那个特定的实体?
9 个解决方案
#1
43
A solution is to use field based annotation, to declare your fields as protected
and to propose only public getter. Doing so, your objects can not be altered.
解决方案是使用基于字段的注释,将字段声明为受保护的,并只建议使用公共getter。这样,您的对象就不能被修改。
(This solution is not entity specific, it is just a way to build immutable objects)
(这个解决方案不是实体特定的,它只是构建不可变对象的一种方法)
#2
22
You can create a bullet proof safety net for your entity with JPA lifecycle listeners.
您可以使用JPA生命周期监听器为您的实体创建一个防弹安全网。
- PRO: JPA standard - not hibernate specific
- PRO: JPA标准-不是特定于hibernate的
- PRO: very safe
- 正方观点:非常安全
- CON: only shows write attempts at runtime. If you want a compile time check, you should not implement setters.
- 缺点:只显示运行时的写尝试。如果需要编译时检查,则不应该实现setter。
In your entity add an EntityListener
like this:
在您的实体中添加如下内容:
@Entity
@EntityListeners(PreventAnyUpdate.class)
public class YourEntity {
// ...
}
Implement your EntityListener
, to throw an exception if any update occurs:
实现你的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("...");
}
}
#3
21
If your JPA implementation is hibernate - you could use the hibernate Entity annotation
如果您的JPA实现是hibernate——您可以使用hibernate实体注释
@org.hibernate.annotations.Entity(mutable = false)
Obviously this will tie your model to hibernate though.
显然,这将绑定您的模型到hibernate。
#4
14
Hibernate also has a org.hibernate.annotations.Immutable
annotation that you can put on the type, method, or field.
Hibernate也有一个org. Hibernate .annotation。可以放在类型、方法或字段上的不可变注释。
#5
13
I think what you are looking for is your entity to be Immutable. Hibernate supports this; JPA(at least JPA 1.0) does not. I suppose you can only control this by providing only getters and make sure that the getters return only immutable values.
我认为你在寻找的是你的实体是不可变的。Hibernate支持;JPA(至少是JPA 1.0)没有。我想您只能通过只提供getter来控制它,并确保getter只返回不可变的值。
#6
11
IIRC you could set every field to insertable = false
and updatable = false
in your @Column
annotations, but I'm sure there must be a better method... :)
IIRC可以在@Column注释中将每个字段设置为insertable = false和updatable = false,但我确信一定有更好的方法……:)
I don't suppose this helps?
我不认为这有用吗?
#7
10
Eclipselink implementation also offers you the @ReadOnly
annotation at the entity level
Eclipselink实现还提供实体级的@ReadOnly注释
#8
6
This is probably going to catch me a downvote because I always get downvoted for suggesting it, but you could use AspectJ in several ways to enforce this:
这可能会让我投反对票,因为我总是因为提出建议而被否决,但是你可以用几个方法来实施AspectJ:
Either automate Mac's solution (make AspectJ inject the @Column
annotation):
或者是自动化Mac的解决方案(让AspectJ注入@Column注释):
declare @field : (@Entity *) *.* : @Column(insertable=false);
Or declare a compiler error for all access to set methods:
或为所有对set方法的访问声明编译器错误:
declare error : execution((@Entity *) *.set*(*) );
Downside: you need to add AspectJ compilation to your build, but that's easy if you use ant or maven
缺点:您需要将AspectJ编译添加到您的构建中,但是如果使用ant或maven,这很简单。
#9
2
If you are using spring-data or are otherwise using the Repository pattern, don't include any save / update / create / insert / etc methods in the Repository for that particular entity. This can be generalized by having a base class / interface for readonly entities, and an updatable one that extends the readonly one for updatable entities. As other posters have pointed out, the setters may also be made non-public to avoid developers accidentally setting values that they are then unable to save.
如果您正在使用spring-data或者正在使用存储库模式,请不要在存储库中为该特定实体包含任何保存/更新/创建/插入/等等方法。这可以通过拥有一个readonly实体的基类/接口和一个可更新的接口来推广,该接口扩展了可更新实体的readonly。正如其他海报所指出的,定居者也可能被禁止公开,以避免开发人员意外地设置他们无法保存的值。
#1
43
A solution is to use field based annotation, to declare your fields as protected
and to propose only public getter. Doing so, your objects can not be altered.
解决方案是使用基于字段的注释,将字段声明为受保护的,并只建议使用公共getter。这样,您的对象就不能被修改。
(This solution is not entity specific, it is just a way to build immutable objects)
(这个解决方案不是实体特定的,它只是构建不可变对象的一种方法)
#2
22
You can create a bullet proof safety net for your entity with JPA lifecycle listeners.
您可以使用JPA生命周期监听器为您的实体创建一个防弹安全网。
- PRO: JPA standard - not hibernate specific
- PRO: JPA标准-不是特定于hibernate的
- PRO: very safe
- 正方观点:非常安全
- CON: only shows write attempts at runtime. If you want a compile time check, you should not implement setters.
- 缺点:只显示运行时的写尝试。如果需要编译时检查,则不应该实现setter。
In your entity add an EntityListener
like this:
在您的实体中添加如下内容:
@Entity
@EntityListeners(PreventAnyUpdate.class)
public class YourEntity {
// ...
}
Implement your EntityListener
, to throw an exception if any update occurs:
实现你的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("...");
}
}
#3
21
If your JPA implementation is hibernate - you could use the hibernate Entity annotation
如果您的JPA实现是hibernate——您可以使用hibernate实体注释
@org.hibernate.annotations.Entity(mutable = false)
Obviously this will tie your model to hibernate though.
显然,这将绑定您的模型到hibernate。
#4
14
Hibernate also has a org.hibernate.annotations.Immutable
annotation that you can put on the type, method, or field.
Hibernate也有一个org. Hibernate .annotation。可以放在类型、方法或字段上的不可变注释。
#5
13
I think what you are looking for is your entity to be Immutable. Hibernate supports this; JPA(at least JPA 1.0) does not. I suppose you can only control this by providing only getters and make sure that the getters return only immutable values.
我认为你在寻找的是你的实体是不可变的。Hibernate支持;JPA(至少是JPA 1.0)没有。我想您只能通过只提供getter来控制它,并确保getter只返回不可变的值。
#6
11
IIRC you could set every field to insertable = false
and updatable = false
in your @Column
annotations, but I'm sure there must be a better method... :)
IIRC可以在@Column注释中将每个字段设置为insertable = false和updatable = false,但我确信一定有更好的方法……:)
I don't suppose this helps?
我不认为这有用吗?
#7
10
Eclipselink implementation also offers you the @ReadOnly
annotation at the entity level
Eclipselink实现还提供实体级的@ReadOnly注释
#8
6
This is probably going to catch me a downvote because I always get downvoted for suggesting it, but you could use AspectJ in several ways to enforce this:
这可能会让我投反对票,因为我总是因为提出建议而被否决,但是你可以用几个方法来实施AspectJ:
Either automate Mac's solution (make AspectJ inject the @Column
annotation):
或者是自动化Mac的解决方案(让AspectJ注入@Column注释):
declare @field : (@Entity *) *.* : @Column(insertable=false);
Or declare a compiler error for all access to set methods:
或为所有对set方法的访问声明编译器错误:
declare error : execution((@Entity *) *.set*(*) );
Downside: you need to add AspectJ compilation to your build, but that's easy if you use ant or maven
缺点:您需要将AspectJ编译添加到您的构建中,但是如果使用ant或maven,这很简单。
#9
2
If you are using spring-data or are otherwise using the Repository pattern, don't include any save / update / create / insert / etc methods in the Repository for that particular entity. This can be generalized by having a base class / interface for readonly entities, and an updatable one that extends the readonly one for updatable entities. As other posters have pointed out, the setters may also be made non-public to avoid developers accidentally setting values that they are then unable to save.
如果您正在使用spring-data或者正在使用存储库模式,请不要在存储库中为该特定实体包含任何保存/更新/创建/插入/等等方法。这可以通过拥有一个readonly实体的基类/接口和一个可更新的接口来推广,该接口扩展了可更新实体的readonly。正如其他海报所指出的,定居者也可能被禁止公开,以避免开发人员意外地设置他们无法保存的值。