首页 > 解决方案 > Hibernate:如何使实体和所有关联默认为只读?(或从会话中自动驱逐关联)

问题描述

我有一个属于客户实体的实体。我希望包括所有关联的实体都是只读的。

public class Foo{

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "customer_id")
    private Customer customer;

    @Basic
    @Column(name = "firstname")
    private String firstName;

    // getters for both fields ....

}

这是我想要的:

  1. 不应持续调用 foo 的 setter。
  2. 对 myFoo.getCustomer() 的调用应返回一个只读客户,以便对诸如 myFoo.getCustomer().setSomething("should not be persisted") 之类的设置器的调用不起作用。

例子:

List<Foo> list = fooDAO.getList();
for (Foo foo : liust) {
  String f1 = foo.getCustomer().getSomeField(); // should work
  foo.getCustomer.setSomeField("change that should not be persisted"); // calling this setter should not have an effect or should even throw an UnsupportedOperationException() or something

  foo.setFirstName("change should not be persisted"); // also this should not be persisted.
}

目前我对协会的解决方案是一种手册:

public Customers getCustomer() {
    // detach the referenced object from the Hibernate session
    // to avoid that changes to these association are persisted to the database
    getCustomersDAO().evict(customer); // calls session.evict(o) under the hood
    return customer;
}

这是我的问题:有什么方法可以避免将关联更改保留到数据库中?例如使用注释?

一般来说,我希望这种行为成为默认行为。但也应该允许更改持久化。所以我需要它可配置。所以我想在查询级别上做这件事。

我的环境:

标签: javahibernate

解决方案


我遇到了这个问题。我将文件名作为对象的属性存储在数据库中,然后在读取它以反映基于环境的存储路径后尝试在应用程序中对其进行操作。我尝试将 DAO 事务设置为只读,并且休眠仍然将属性更改保留到数据库。然后,我在操作该属性之前使用了 entityManager.detach(object),这很有效。但是,我后来陷入了一些问题,即其他依赖于对象自动持久性到数据库的服务方法没有表现出应有的行为。

我学到的教训是,如果你需要操纵一个你不想持久化的对象的属性,那么使用它自己的 getter 和 setter 为该对象创建一个“瞬态”属性,并确保瞬态属性 setter 不是t 从实体模型传递属性,然后被操纵。例如,如果你有一个 String 的属性“filename”,并且你有一个临时属性“s3key”,那么“s3Key”属性设置器应该做的第一件事就是将一个新的 String 对象传递给设置器以供它使用在操纵中。

@Transient
private String s3Key;

public String getS3Key {
   String s3key = s3Prefix + "/" + <other path info> + this.filename;
   return s3key;
}

虽然 jpa/hibernate 的所有“只读”和“分离”内容都允许自定义处理对象到数据库的持久性,但似乎只是为了自定义对象的行为到那个程度会导致以后的可支持性问题,当在其他服务功能中预期或依赖自动持久化实体更改。我自己的经验是,最好使用一种编程模式,即利用瞬态属性来处理您不希望保留的实体的更改。


推荐阅读