如何使实体只读?

时间:2022-09-11 16:48:56

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。正如其他海报所指出的,定居者也可能被禁止公开,以避免开发人员意外地设置他们无法保存的值。