本文共 4602 字,大约阅读时间需要 15 分钟。
Each interface has a matching implementation
supported by Hibernate, and it’s important that you use the right combination.
先说一个 @JoinColumn的问题。
这个注解是用来说明关联列的信息的。
按自然的做法是:多在Many端上描述这些信息,因为从DB表上来看,关联列者是many端的表上外键列。
但是,如果是单向的one-to-many时就只能在one上映射了。这时候看起来会有些让人迷惑。
再补补集合中的一些知识吧,有些确实生疏了:
关于Set下面的几个具体实际的对比:
- * HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;
- * LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代;
- * TreeSet:提供一个使用树结构存储Set接口的实现,通过提供元素比较器,使得集合在插入过程中直接有序。
LinkedHashSet没有实现什么特殊接口用以表明它是有序的。
1.关于Set的映射
在基于xml配制的情况下如果你的只是声明一个普通的set,那个在实例化对象时,hibernate会生成HashSet。
而如果在set的配制中加入order-by,hibernate就会生成LinkedHashSet了!这样就是一个有序的集合了。
关于Set的排序和Hibernate如何生成Set实例的问题:
内存排序:
Set映射有两种排序方式,一是使用映射文件中的sort属性,一般需要自己实现一个java.util.Comparator,sort属性
指定自己实现的比较类,hibernate返回给客户的实际是Set的TreeSet实现,将该比较类作为treeSet的比较器,这种
排序是在内存中进行的,可以在比较器中按实体类的某个字段排序或实现更复杂的排序方法,非常灵活,但是要自己实
现比较器,麻烦一些。
以下是两个例子:
<set name="aliases" table="person_aliases" sort="natural" ><key column="person"/><element column="name" type="string"/></set>
<map name="holidays" sort="my.custom.HolidayComparator" ><key column="year_id"/><map-key column="hol_name" type="string"/><element column="hol_date" type="date"/></map>
sort 属性中允许的值包括 unsorted,natural 和某个实现了 java.util.Comparator 的类的名称。
数据库排序:
另一种方法是使用映射中的order-by属性,可以指定表中的一个排序字段,排序是在数据库中进行的,hibernate返回
是LinkedHashSet实现,可以保持对象的前后次序。
以下又是两个例子
<set name="aliases" table="person_aliases" order-by="lower(name) asc" ><key column="person"/><element column="name" type="string"/></set><map name="holidays" order-by="hol_date, hol_name" ><key column="year_id"/><map-key column="hol_name" type="string"/><element column="hol_date type="date"/></map>
所以参考中说在实体类中定义子集合时不要定义成HashSet,而应该是Set接口,因为它返回的不一定是HashSet。 对于List(Bag映射),可以指定order-by排序字段,并不需要index列。
关于List的影射:
首先要强调的是:很多时候,我们的java.util.List可以映射成bag的!
因为大多数时候,我们需要的只是一组从数据库里取出的数据,至于顺序,只能是从数据库中查出时的先后顺序(按ID升序)。在这种需求下,如果要使用set,那么必须要在映射中加入order-by,而如果使用list(xml中的list),那么还需要额外的index-column!所以最好的方案就是用bag.
在基于注解的配制方式时:
如果在List字段上不加@IndexColumn,那么这个List就会被映射成Hibernate里bag
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的。
关于@CollectionOfElements
Hibernate一直强调值对象与实体类之间差异,这在集合类型的映射上体现的极为明显。在映射集合类型的值对象进,使用xml有<element>, 使用注解则有@CollectionOfElements
关于@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)
The collection is no longer initialized if you call size(), contains(), or isEmpty().
org.hibernate.annotations.LazyCollectionOption.EXTRA是较一般lazy loading更加lazy,或者说更加智能的选项,当访问集合的size(), contains(), or isEmpty()时,并不加载整个集合,这对加载大集合来说很适用!
使用了@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA),
集合变得更“聪明”,调用size()时,不会加载集合,打出的sql是:select
count(id) from Thread where forumId =? 没有使用@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)时,只要用的size(),就会导致整个集合加载!以是打出的SQL select threads0_.forumId as forumId4_, threads0_.id as id4_, threads0_.id as id5_3_, threads0_.creationTime as creation2_5_3_, threads0_.forumId as forumId5_3_, threads0_.modifiedTime as modified3_5_3_, threads0_1_.subjectId as subjectId6_3_, post1_.id as id4_0_, post1_.authorId as authorId4_0_, post1_.creationTime as creation2_4_0_, post1_.isSubject as isSubject4_0_, post1_.messageBody as messageB4_4_0_, post1_.modifiedTime as modified5_4_0_, post1_.quotedPostId as quotedPo8_4_0_, post1_.title as title4_0_, user2_.id as id0_1_, user2_.accountNonExpired as accountN2_0_1_, user2_.accountNonLocked as accountN3_0_1_, user2_.credentialsNonExpired as credenti4_0_1_, user2_.email as email0_1_, user2_.enabled as enabled0_1_, user2_.password as password0_1_, user2_.username as username0_1_, user2_.version as version0_1_, post3_.id as id4_2_, post3_.authorId as authorId4_2_, post3_.creationTime as creation2_4_2_, post3_.isSubject as isSubject4_2_, post3_.messageBody as messageB4_4_2_, post3_.modifiedTime as modified5_4_2_, post3_.quotedPostId as quotedPo8_4_2_, post3_.title as title4_2_ from Thread threads0_ left outer join Thread_Subject threads0_1_ on threads0_.id=threads0_1_.threadId left outer join Post post1_ on threads0_1_.subjectId=post1_.id left outer join User user2_ on post1_.authorId=user2_.id left outer join Post post3_ on post1_.quotedPostId=post3_.id where threads0_.forumId=?转载地址:https://laurence.blog.csdn.net/article/details/5541817 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!