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