关于hibernate中一对多映射 list 和set映射的使用区别

http://www.114java.com/javakaiyuankuangjia/hibernate/201001/853.html

hibernate

在双向关联的hibernate在一对多配置的时候默认总是给我们提供set类型,最近在做电力系统后台用户角色的时候就遇到了这个问题。

因为你获得的set是一个无序的集合,因此,在现实页面上的时候可能每次都会改变,在hibernate的配置文档中

<set name="roles" table="USER_ROLE" cascade="save-update" inverse="true" outer-join ="false" lazy="false" order-by="ROLEID" >
<key column="USERID" />
<many-to-many class="com.fjnetpower.zzjf.business.model.entities.Role" column="ROLEID" />
</set>

加上order-by这个属性即可解决问题

关于这个问题的深入研究:

1、其实hibernate是有提供list映射的, list就是bag类型,bag适合关联的集合类中有排序需求

在配置list的时候,也有几种方法:指定list-index,这也就要在数据库中对应创建一个字段表示顺序

对于一对多关联当中的List,需要在数据库里面维护一个index列,如果List当中的某个元素被删除,那么Hibernate会

连续发送多条update语句,更新后续所有元素的index列,以确保index的连续性(在inverse为false的情况下),如果

你选择自己维护index列,也同样会面临这个问题,甚至更棘手(在inverse为true的情况下),所以List被谨慎的使用在

极其罕见的场合。

但是,这里所说的要特别慎用list是指的hibernate映射文件中的list类型,而不是实体类中的List类型。映射文件中

用Bag类型,在实体类中是可以对应List的。

2、至于说排序,List(Bag映射)和Set都是可以排序的,hibernate有自己的Set、List、Map实现,其内部根据使

用的排序方式使用Java.util中的各种不排序的或排序的集合实现类。

Set映射有两种排序方式,一是使用映射文件中的sort属性,一般需要自己实现一个java.util.Comparator,sort属性

指定自己实现的比较类,hibernate返回给客户的实际是Set的TreeSet实现,将该比较类作为treeSet的比较器,这种

排序是在内存中进行的,可以在比较器中按实体类的某个字段排序或实现更复杂的排序方法,非常灵活,但是要自己实

现比较器,麻烦一些。

另一种方法是使用映射中的order-by属性,可以指定表中的一个排序字段,排序是在数据库中进行的,hibernate返回

是LinkedHashSet实现,可以保持对象的前后次序。

所以参考中说在实体类中定义子集合时不要定义成HashSet,而应该是Set接口,因为它返回的不一定是HashSet。

对于List(Bag映射),可以指定order-by排序字段,并不需要index列。

个人感觉List使用起来方便一些,所以一般在实体类中定义List,对应映射中的Bag类型。

3、说到关联使用Set可以避免重复对象可能也只是自我感觉可靠一些,实际上不会有重复对象出现,每个关联对象都有

自己的主键id,获取集合时只是简单的外键关联查询,没有复杂的查询,哪来的重复对象呢。如果集合里不是自己定义

的pojo而是String、Integer等简单类型倒是可能会重复,不过那是特殊的应用了。对于hql等查询才需要考虑可能出现

的重复对象问题(同一对象的重复引用),但是hibernate并没有提供返回Set的查询方法,用query.iterate()也会有重复对象。

因为相同id的对象在session中只会保存一份,所以如果始终在同一session中那么不实现equals和hashCode方法也

可以放心的使用集合的contains等方法,不管是用hql查询还是load、get方法,对于同一id返回的都是同一个对象,即

使对于因延迟加载而代理的对象也是始终返回该代理对象,忽然想到对于get方法如果某id前面有过代理对象,虽然一定会加

载实体对象数据,但返回的还是该代理对象,以前一直觉得很奇怪,可能就是基于这样的考虑。看来OpenSessionInView方

法很有好处啊。

如果要实现equals和hashCode方法,当然首先要考虑到id字段,忽然想到光id字段还不够,因为对于新建的对象,id为

null,如果新建两个对象然后放到Set中,会认为两个对象相等,只能放入第一个,保存时也只能保存一个,反而不重写

equals和hashCode时倒是没有问题

展开阅读全文

没有更多推荐了,返回首页