如何使实体成为只读?

时间:2011-02-25 09:23:22

标签: java jpa

使用JPA使实体成为只读的正确方法是什么?我希望我的数据库表永远不会以编程方式进行修改。

我想我明白我应该用LockModeType.READ锁定我的对象。从数据库中检索后,是否可以使用注释使我的实体直接锁定?或者,我是否必须乱用并覆盖该特定实体的通用DAO?

9 个答案:

答案 0 :(得分:44)

解决方案是使用基于字段的注释,将您的字段声明为protected并仅建议公共getter。这样做,您的对象无法更改。

(此解决方案不是特定于实体的,它只是一种构建不可变对象的方法)

答案 1 :(得分:29)

您可以使用JPA生命周期监听器为您的实体创建防弹安全网。

  • PRO:JPA标准 - 不是特定于hibernate的
  • PRO:非常安全
  • CON:仅显示运行时的写入尝试。如果您想要编译时检查,则不应实现setter。

在您的实体中添加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*(*) );

下行:您需要在构建中添加AspectJ编译,但如果您使用antmaven

,这很容易

答案 8 :(得分:3)

如果您正在使用spring-data或以其他方式使用Repository模式,请不要在该特定实体的Repository中包含任何save / update / create / insert / etc方法。这可以通过为只读实体提供基类/接口来推广,并且可以为可更新实体扩展可读的实体。正如其他海报所指出的那样,设置者也可能是非公开的,以避免开发人员意外设置他们无法保存的值。

相关问题