hibernate小结

一、PO的数据类型设置

int还是IntegerInteger允许为null

Hibernate既可以访问Field也可以访问Property,访问Property是只是调用getXXX()、setXXX()方法,因此在fromCustomerwherec.name=’Tom’HQL中,name属性不需要存在,只要getName()存在就可以了。

二、Hibernate映射

1、映射复合主键

Java代码

1.主键类

2.PublicclassCustomerIdimplementsSerializable{

3.PrivatefinalStringname;

4.PrivatefinalStringcompanyid;

5.}

6.映射文件

7.<classname=”test.Customer”table=”CUSTOMERS”>

8.<composite-idname=”customerId”class=”test.CustomerId”>

9.<key-propertyname=”name”column=”NAME”type=”string”/>

10.<key-propertyname=”companyId”column=”COMPANY_ID”type=”long”/>

11.</composite-id>

12.<versionname=”varsion”column=”VERSION”unsaved-value=”0”/>

13.<many-to-onename=”company”class=”test.Company”column=”COMPANY_ID”insert=”false”update=”false”/>

14.<setname=”orders”lazy=”true”inverse=”true”>

15.<key>

16.<column=”NAME”/>

17.<column=”COMPANY_ID”/>

18.</key>

19.</set>

20.</class>

21.<classname=”test.Order”table=”ORDERS”>

22.<many-to-onename=”customer”class=”test.Customer”>

23.<column=”NAME”/>

24.<column=”COMPANY_ID”/>

25.</many-to-one>

26.</class>

27.

28.或

29.

30.<classname=”test.Customer”table=”CUSTOMERS”>

31.<composite-idname=”customerId”class=”test.CustomerId”>

32.<key-propertyname=”name”column=”NAME”type=”string”/>

33.<key-many-to-onename=”company”class=”test.Company”column=”COMPANY_ID”/>

34.

35.</composite-id>

36.<versionname=”varsion”column=”VERSION”unsaved-value=”0”/>

37.<setname=”orders”lazy=”true”inverse=”true”>

38.<key>

39.<column=”NAME”/>

40.<column=”COMPANY_ID”/>

41.</key>

42.</set>

43.</class>

44.<classname=”test.Order”table=”ORDERS”>

45.<many-to-onename=”customer”class=”test.Customer”>

46.<column=”NAME”/>

47.<column=”COMPANY_ID”/>

48.</many-to-one>

49.</class>

2、映射组成关系

Java代码

1.<hibernate-mapping>

2.<classname=”Customer”table=”CUSTOMERS”>

3.<property/>

4.<componentname=”homeAddress”class=”Address”>

5.<parentname=”customer”/>

6.<property/>

7.</component>

8.<componentname=”comAddress”class=”Address”>

9.<parentname=”customer”/>

10.<property/>

11.</component>

12.</class>

13.</hibernate-mapping>

14.

15.PublicclassCustomerimplementsSerializable{

16.AddresshomeAddress;

17.AddresscomAddress;

18.}

19.PublicclassAddressimplementsSerializable{//是VO不是PO不能单独Save,也不能关联。

20.Customercustomer;

21.}

3、映射聚合关系

Java代码

1.<set/idbagname=”images”table=”IMAGES”lazy=”true”>

2.<keycolumn=”CUSTOMER_ID”/>

3.<composite-elementclass=”Image”>

4.<parentname=”customer”/>

5.<property/>

6.<property/>

7.</composite-element>

8.</set/idbag>

9.

10.<mapname=”images”table=”IMAGES”lazy=”true”>

11.<keycolumn=”CUSTOMER_ID”/>

12.<indextype=”string”column=”IMAGE_NAME”/>

13.<composite-elementclass=”Image”>

14.<parentname=”customer”/>

15.<property/>

16.<property/>

17.</composite-element>

18.</map>

4、映射继承关系

Java代码

1.DOClass{

2.id

3.}

4.ClassAextendsDOClass{

5.A1

6.}

7.

8.ClassCextendsClassA{

9.C1

10.}

11.

12.ClassDextendsClassA{

13.D1

14.}

15.

16.ClassGextendsClassD{

17.G1

18.}

19.

20.ClassHextendsClassD{

21.H1

22.}

23.

24.ClassBextendsDOClass{

25.B1

26.}

27.

28.ClassEextendsClassB{

29.E1,e2,e3,e4,e5,e6

30.}

31.

32.ClassFextendsClassB{

33.F1,f2,f3,f4,f5,f6,f7

34.}

35.

36.TABLE_A{ID(PK),A_TYPE(discriminator),A1,C1,D1,G1,H1}

37.TABLE_B{ID(PK),B1}

38.TABLE_E{B_ID(PK/FK),E1,E2,E3,E4,E5,E6}

39.TABLE_F{B_ID(PK/FK),F1,F2,F3,F4,F5,F6,F7}

40.

41.ClassA.hbm.xml

42.<hibernate-mapping>

43.<classname=”ClassA”table=”TABLE_A”discriminator-value=”A”>

44.<id/>

45.<discriminatorcolumn=”A_TYPE”type=”string”/>

46.<propertyname=”a1”column=”A1”/>

47.<sub-classname=”ClassC”discriminator-value=”C”>

48.<propertyname=”c1”column=”C1”/>

49.</sub-class>

50.<subclassname=”ClassD”discriminator-value=”D”>

51.<propertyname=”d1”column=”D1”/>

52.<subclassname=”ClassG”discriminator-value=”G”>

53.<propertyname=”g1”column=”G1”/>

54.</subclass>

55.<subclassname=”ClassH”discriminator-value=”H”>

56.<propertyname=”h1”column=”H1”/>

57.</subclasss>

58.</subclass>

59.</class>

60.</hibernate-mapping>

61.ClassB.hbm.xml

62.<hibernate-mapping>

63.<classname=”ClassB”table=”TABLE_B”>

64.<id/>

65.<propertyname=”b1”column=”B1”/>

66.<joined-subclassname=”ClassE”table=”TABLE_E”>

67.<keycolumn=”B_ID”/>

68.<propertyname=”e1”column=”E1”/>

69.<propertyname=”e2”column=”E2”/>

70.<propertyname=”e3”column=”E3”/>

71.<propertyname=”e4”column=”E4”/>

72.<propertyname=”e5”column=”E5”/>

73.<propertyname=”e6”column=”E6”/>

74.</joined-subclass>

75.<joined-subclassname=”ClassF”table=”TABLE_F”>

76.<keycolumn=”B_ID”/>

77.<propertyname=”f1”column=”F1”/>

78.<propertyname=”f2”column=”F2”/>

79.<propertyname=”f3”column=”F3”/>

80.<propertyname=”f4”column=”F4”/>

81.<propertyname=”f5”column=”F5”/>

82.<propertyname=”f6”column=”F6”/>

83.<propertyname=”f7”column=”F7”/>

84.</joined-subclass>

85.</class>

86.</hibernate-mapping>

5、映射Bag,List和Map

IDBag

Java代码

1.IMAGES{ID(PK),CUSTOMER_ID(FK),FILENAME}

2.Listimages=newArrayList();

3.Customer.hbm.xml

4.

5.<idbagname=”images”table=”IMAGES”lazy=”true”>

6.<collection-idtype=”long”column=”ID”>

7.<generatorclass=”increment”/>

8.</collection-id>

9.<keycolumn=”CUSTOMER_ID”/>

10.<elementcolumn=”FILENAME”type=”string”not-null=”true”/>

11.</idbag>

List

Java代码

1.IMAGES{CUSTOMER_ID(PK/FK),POSITION(PK),FILENAME}

2.Listimages=newArrayList();

3.Customer.hbm.xml

4.<listname=”images”table=”IMAGES”lazy=”true”>

5.<indexcolumn=”POSITION”/>

6.<keycolumn=”CUSTOMER_ID”/>

7.<elementcolumn=”FILENAME”type=”string”not-null=”true”/>

8.</list>

Map

Java代码

1.IMAGES{CUSTOMER_ID(PK/FK),IMAGE_NAME(PK),FILENAME}

2.Mapimages=newHashMap();

3.<mapname=”images”table=”IMAGES”lazy=”true”>

4.<keycolumn=”CUSTOMER_ID”/>

5.<indexcolumn=”IMAGE_NAME”type=”string”/>

6.<elementcolumn=”FILENAME”type=”string”not-null=”true”/>

7.</map>

8.

9.Setidbagmap支持数据库排序orderby=”ID”

10.Setmap支持内存排序sort=“MyComparator”

6、映射一对一关联关系特殊情况一

Java代码

1.PublicclassCustomer{

2.AddresshomeAddress;

3.AddresscomAddress;

4.}

5.

6.Customer.hbm.xml

7.<many-to-onename=”homeAddress”class=”Address”column=”HOME_ADDRESS_ID”cascade=”all”unique=”true”/>

8.<many-to-onename=”comAddress”class=”Address”column=”COM_ADDRESS_ID”cascade=”all”unique=”true”/>

9.

10.Address.hbm.xml

11.<one-to-onename=”address”class=”Customer”property-ref=”homeAddress”/>

映射一对一关联关系主键映射

Java代码

1.Customer.hbm.xml

2.<one-to-onename=”address”class=”Address”cascade=”all”/>

3.Address.hbm.xml

4.<classname=”address”>

5.<id>

6.<generatorclass=”foreign”>

7.<paramname=”property”>customer</param>

8.</generator>

9.</id>

10.<one-to-onename=”customer”class=”Customer”constrained=”true”/>

11.</class>

7、映射一对多关联

Java代码

1.<classname="Person">

2.<idname="id"column="personId">

3.<generatorclass="native"/>

4.</id>

5.<many-to-onename="address"column="addressId"not-null="true"/>

6.</class>

7.

8.<classname="Address">

9.<idname="id"column="addressId">

10.<generatorclass="native"/>

11.</id>

12.<setname="people"inverse="true">

13.<keycolumn="addressId"/>

14.<one-to-manyclass="Person"/>

15.</set>

16.</class>

8、映射多对多关联

Java代码

1.<setname=”items”table=”CATEGORY_ITEM”lazy=”true”cascade=”save-update”>

2.<keycolumn=”CATEGORY_ID”>

3.<many-to-manyclass=”Item”column=”ITEM_ID”/>

4.</set>

三、Inverse与cascade

Inverse

应该将Set的inverse属性设置为true,如果为many-to-many需要将一方设置为true

如Customer:Order为1:N双向关联,将Customer的Set的inverse设置为true,表示Customer与Order之间的关联关系由Order端来维护,如customer.getOrders().addOrder(o)不会更新Customer与Order之间的关联关系,而order.setCustomer(o)才会更新Customer与Order之间的关联关系。

Cascade

Save-update保存、更新Customer会同步更新Order.

Delete同步删除

All包含save-update和delete操作,另外调用当前对象的evice或者lock时,对关联对象也调用相应方法。

Delete-orphan删除所有和当前对象解除关联关系的对象。

All-delete-orphan当关联双方为父子关系是(父亲控制孩子的持久化生命周期),如果父方删除,子方自动删除(同delete),如果子方无父亲,子方应删除。包含Delete和all-orphan的行为。

四、Hibernate缓存

Session缓存(一级缓存),每一session确保自己的缓存的所有的持久对象唯一

通过调用session.setFlushMode()可设定缓存的清理模式,缓存的清理模式有三种:

FlushMode.AUTO:query、commit和flush的时候清理缓存。

FlushMode.COMMIT:commit和flush的时候清理缓存。

FlushMode.NEVER:只有在调用session.flush()的时候才清理缓存。

Session只有在清理缓存的时候才会执行相应的sql操作。

可以使用session.evict()和session.clear()清空缓存。

Save、update、query都加入Session缓存

Selectc.ID,c.Name,c.age,o.ORDER_NUM,o.CUSTOMER_IDfromCustomerc,innerjoinc.ordersc除外。

SessionFactory缓存(二级缓存)

Java代码

1.<classname=”Category”table=”CATEGORYS”>

2.<cacheusage=”read-write”/>

3.<id/>

4.<setname=”items”inverse=”true”lazy=”true”>

5.<cacheusage=”read-write”/>

6.<key…/>

7.</set>

8.</class>

9.<classname=”Item”>

10.<cacheusage=”read-write”/>

11.<id/>

12.</class>

13.

14.Hibernate.cache.provider=…………EhCacheProvider

15.Hibernate.cache.user_query_cache=true

16.

17.Ehcache.xml

18.<ehcache>

19.<diskStorepath=”c:\\temp”/>

20.<defaultCache

21.maxElementsInMemory=”10000”

22.eternal=”false”

23.timeToIdleSeconds=”120”

24.timeToLiveSeconds=”120”

25.overflowToDisk=”true”/>

26.<cachename=”Category”

27.maxElementsInMemory=”10000”

28.eternal=”false”

29.timeToIdleSeconds=”120”

30.timeToLiveSeconds=”120”

31.overflowToDisk=”true”/>

32.

33.<cachename=”Category.Items”

34.maxElementsInMemory=”10000”

35.eternal=”false”

36.timeToIdleSeconds=”120”

37.timeToLiveSeconds=”120”

38.overflowToDisk=”true”/>

39.

40.<cachename=”Item”

41.maxElementsInMemory=”10000”

42.eternal=”false”

43.timeToIdleSeconds=”120”

44.timeToLiveSeconds=”120”

45.overflowToDisk=”true”/>

46.

47.<cachename=”customerQueries”…./><!—设置查询缓存

48.

49.</ehcache>

Queryq=session.createQuery();

q.setCacheable(true);

q.setCacheRegion(“customerQueries”);

SessionFactory.evict(),SessionFactory.evictCollection()清除二级缓存。

直接调用JDBCAPI不会使用任何缓存。

二级缓存适合查询较多但是很少更新的情况。

尽量对数据库的所有操作由Hibernate来完成,而不要用其它方式对数据库进行操作,否则可能与缓存冲突,当然如果对缓存有深入研究的除外。

五、临时对象(TransientObject)、持久对象(PersistentObject)和游离对象(DetachedObject)

临时对象:表示对象的主键不存在(OID不存在),Hibernate通过key的unsave-value或者version的unsaved-value来判断是否为临时对象。Session对临时对象的唯一操作应该是save()。

持久对象:在session缓存中存在持久对象,数据库中存在相应纪录。

游离对象:数据库中有相应纪录,session中不存在持久对象,可通过session.evict()获得。

Session缓存中存在,数据库中不存在,这是什么类型的对象?实际这种情况不存在,因为所有的Session操作均在事务中进行,缓存中的数据是通过save、update或者query生成,而save或者update得到的是数据库的独占锁,因此其它事务没有可能删除数据库中的数据。而query获得的是数据库的共享锁,因此其它事务也不可能获得独占锁来更新数据。因此在一个事务内部session缓存才有意义,如果脱离事务,仅仅是只读操作也可能导致session缓存中存在数据库中根本不存在相应纪录的持久性对象。

六、Hibernate的检索策略

设定批量检索数量batch-size

外连接深度控制hibernate.max_fetch_depth

类级别检索load、get和find。其中load可以设置延迟检索(cglib生成代理类,可通过Hibernate.initialize()初始化),这也是load和get的区别之一。Get/find立即检索,与是否设置延迟无关。

关联检索立即检索,延迟检索,迫切左外连接检索。Set/list/map等,无论是否延迟检索得到的都是代理集合类。而非HashSet,ArrayList等。

Lazy与outer-joint

False,false立即检索

False,true迫切左外连接,

True,false延迟检索

Many-to-one的outer-join属性

Auto:Customer的lazy为true则延迟加载,否则迫切左外连接

True:迫切左外连接

False:延迟加载或者立即加载由Customer的lazy决定。

One-to-one的延迟加载策略

<one-to-onename=”customer”class=”Customer”constrained=”true”/>

HQL会忽略迫切左外连接检索和lazy(只有load才为代理对象)策略。

Session.find(“fromCustomercascleftjoinfetchc.orderswherec.id=1”)

Hibernate的检索方式

HQL、NativeSql和QBC

FromCustomercinnerjoinc.orderso查询结果保存到session缓存

Selectc.ID,c.Name,c.age,o.ORDER_NUM,o.CUSTOMER_IDfromCustomerc,innerjoinc.ordersc查询结果不存入Session缓存。

七、Hibernate并发控制

乐观锁:VERSION或者timestamp控制,session.lock()立刻进行版本检查,session.update(),update的时候执行版本检查。

悲观锁:selectforupload,session.get(Customer.class,newLong(1),LockMode.UPGRADE)

总结:本文绝大多数为摘录内容,有些地方加上自己的理解,有不对之处恳请批评指正。看了书,阅读了相关帖子后,感觉学习Hibernate的重点应该是Hibernate的缓存策、查询和如何提高性能方面。

另外说点自己的感受,本人做项目到现在都是在设计阶段先有关系模型后有对象模型(其实一个Table一个对象),在这种情况下Hibernate的优势大大降低了,其实是为了Hibernate而Hibernate了,个人感觉在先有关系模型的情况下用Hibernate的意义不大。

如果按照OOAD的开发流程先有对象模型,然后根据对象模型生成关系模型,那应该说用Hibernate用对了地方。毕竟Hibernate对继承、多态,各种复杂的关系都有很好的支持。

相关推荐