Java 如何将Hibernate映射集作为不可修改集加载?

Java 如何将Hibernate映射集作为不可修改集加载?,java,hibernate,collections,immutability,Java,Hibernate,Collections,Immutability,我正在开发的一个应用程序专门使用Hibernate将一组持久对象从数据库提取到内存。应用程序将不时地从数据库刷新内存中的快照,这应该是与数据库的唯一通信 内存中的对象然后用于一系列计算。计算不得修改这些对象。除了某堂课上的意外,我不得不花一天的时间寻找这个虫子。现在我想知道使整个对象树不可变的最佳方法是什么 假设类层次结构如下所示: public class Building { // persistent entity private String name; // hibernate

我正在开发的一个应用程序专门使用Hibernate将一组持久对象从数据库提取到内存。应用程序将不时地从数据库刷新内存中的快照,这应该是与数据库的唯一通信

内存中的对象然后用于一系列计算。计算不得修改这些对象。除了某堂课上的意外,我不得不花一天的时间寻找这个虫子。现在我想知道使整个对象树不可变的最佳方法是什么

假设类层次结构如下所示:

public class Building { // persistent entity
    private String name; // hibernate-mapped property
    private Set<Person> inhabitants; // hibernate-mapped collection

    // getters
}

public class Person { // persistent entity
    private String name; // hibernate-mapped property

    // getters
}
公共类生成{//持久实体
私有字符串名称;//hibernate映射属性
私有集合;//hibernate映射集合
//吸气剂
}
公共类Person{//持久实体
私有字符串名称;//hibernate映射属性
//吸气剂
}
我已通过以下方式阻止客户端访问数据库:

  • 急切地获取所有实体和集合
  • 在Hibernate映射中将所有实体和集合标记为
    mutable=false
  • 不提供任何Hibernate会话实例或状态更改dao方法
现在我要防止的错误是,有人意外地进入
building.getInmobiles().clear()。我可以想到以下几种选择:

  • Getter wrapping:在
    集合中进行
    getincombients
    第一次wrapp
    incombients
    。unmodifiableSet()
    调用,然后返回它

    • 优点:最少的工作,最少的额外代码
    • 缺点:感觉不舒服
  • 包装类:将
    建筑
    重命名为
    可变建筑
    人员
    重命名为
    可变人员
    ,并提供不可变类
    建筑
    人员
    。因为我的应用程序有一个清晰的快照点,所以我可以将记录作为可变对象获取(就像我现在做的那样),制作深度不变的副本,并将对象树呈现给客户端

    • 优点:纯java,没有Hibernate魔法。我开始使用我最喜欢的关键词:
      final
    • 缺点:需要编写和维护更多代码。另外,Hibernate是否将可变实例保留在内存中
  • Hibernate mapping magic:使用一个magic关键字指示Hibernate将它在我的实体对象上设置的集合包装在
    collections.unmodifiableSet()
    或等效文件中。(注意:我使用xml映射文件)

    • 优点:优雅,无需额外代码
    • 缺点:这样的关键字可能不存在
  • Hibernate扩展:使用一个Hibernate扩展点来编写我自己的对象实例化器,并在那里将集合包装在
    集合中。unmodifiableSet()
    中,然后返回它

    • 优点:比破解我的getters更优雅
    • 缺点:这样的扩展点可能不存在
  • 现在我倾向于2,主要是因为我不知道3和4是否可能


    最好的方法是什么?

    选择1,当然。这不是“hacky”,这正是您将属性访问抽象为方法的原因,首先:-)请注意,您应该在Hibernate中使用“field access”,而不是“method”,这样您就不会冒险为Hibernate提供不可修改的集合


    不幸的是,Hibernate没有提供放置不可修改集合的方法,但我认为可以使用@PostLoad事件侦听器在加载对象后修改所有集合

    这似乎是最好的解决办法。我不得不接受这样一个事实:可变类有时是可以的!:)