我的Blog我做主^_^

走向一条通往JAVA的不归路...

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  64 随笔 :: 68 文章 :: 77 评论 :: 0 Trackbacks

一、PO的数据类型设置
int 还是Integer Integer 允许为 null
Hibernate 既可以访问Field也可以访问Property,访问Property是只是调用getXXX()、setXXX()方法,因此在from Customer where c.name=’Tom’ HQL中,name属性不需要存在,只要getName()存在就可以了。

二、Hibernate映射

1、映射复合主键

代码
  1. 主键类   
  2. Public class CustomerId implements Serializable{   
  3.     Private final String name;   
  4.     Private final String companyid;   
  5. }   
  6. 映射文件   
  7. < class   name =”test.Customer”  table =”CUSTOMERS” >   
  8.      < composite-id   name =”customerId”  class =”test.CustomerId” >   
  9.          < key-property   name =”name”  column =”NAME”  type =”string” />   
  10.          < key-property   name =”companyId”  column =”COMPANY_ID”   type =”long” />   
  11.      </ composite-id >   
  12.      < version   name =”varsion”  column =”VERSION”  unsaved-value =”0” />   
  13.      < many-to-one   name =”company”  class =”test.Company”  column =”COMPANY_ID”  insert =”false”  update =”false” />   
  14.      < set   name =”orders”  lazy =”true”  inverse =”true” >   
  15.          < key >   
  16.              < column column =”NAME” />   
  17.              < column column =”COMPANY_ID” />   
  18.          </ key >   
  19.      </ set >   
  20. </ class >   
  21. < class   name =”test.Order”  table =”ORDERS” >   
  22.      < many-to-one   name =”customer”  class =”test.Customer” >   
  23.              < column column =”NAME” />   
  24.              < column column =”COMPANY_ID” />   
  25.      </ many-to-one >   
  26. </ class >   
  27.   
  28. 或   
  29.   
  30. < class   name =”test.Customer”  table =”CUSTOMERS” >   
  31.      < composite-id   name =”customerId”  class =”test.CustomerId” >   
  32.          < key-property   name =”name”  column =”NAME”  type =”string” />   
  33. < key-many-to-one   name =”company”  class =”test.Company”  column =”COMPANY_ID” />   
  34.   
  35.      </ composite-id >   
  36.      < version   name =”varsion”  column =”VERSION”  unsaved-value =”0” />   
  37.      < set   name =”orders”  lazy =”true”  inverse =”true” >   
  38.          < key >   
  39.              < column column =”NAME” />   
  40.              < column column =”COMPANY_ID” />   
  41.          </ key >   
  42.      </ set >   
  43. </ class >   
  44. < class   name =”test.Order”  table =”ORDERS” >   
  45.      < many-to-one   name =”customer”  class =”test.Customer” >   
  46.              < column column =”NAME” />   
  47.              < column column =”COMPANY_ID” />   
  48.      </ many-to-one >   
  49. </ class >   

2、映射组成关系

代码
  1. < hibernate-mapping >   
  2.      < class   name =”Customer”  table =”CUSTOMERS” >   
  3. < property   />   
  4.          < component   name =”homeAddress”  class =”Address” >   
  5.              < parent   name =”customer” />   
  6.              < property />   
  7.          </ component >   
  8.          < component   name =”comAddress”  class =”Address” >   
  9.              < parent   name =”customer” />   
  10.              < property />   
  11.          </ component >   
  12.      </ class >   
  13. </ hibernate-mapping >   
  14.   
  15. Public class Customer implements Serializable{   
  16.     Address homeAddress;   
  17.     Address comAddress;   
  18. }   
  19. Public class Address implements Serializable{//是VO不是PO不能单独Save,也不能关联。   
  20.     Customer customer;   
  21. }  

3、映射聚合关系

代码
  1. < set /idbag  name =”images”  table =”IMAGES”  lazy =”true” >   
  2.      < key   column =”CUSTOMER_ID” />   
  3.      < composite-element   class =”Image” >   
  4.          < parent   name =”customer” />   
  5.          < property />   
  6. < property />   
  7.      </ composite-element >   
  8. </ set /idbag >   
  9.   
  10. < map   name =”images”  table =”IMAGES”  lazy =”true” >   
  11.      < key   column =”CUSTOMER_ID” />   
  12.      < index   type =”string”  column =”IMAGE_NAME” />   
  13.      < composite-element   class =”Image” >   
  14.          < parent   name =”customer” />   
  15.          < property />   
  16. < property />   
  17.      </ composite-element >   
  18. </ map   >   

4、映射继承关系

代码
  1. DOClass{   
  2.    id   
  3. }   
  4. ClassA extends DOClass{   
  5.     A1   
  6. }   
  7.   
  8. ClassC extends ClassA{   
  9.     C1   
  10. }   
  11.   
  12. ClassD extends ClassA{   
  13.     D1   
  14. }   
  15.   
  16. ClassG extends ClassD{   
  17.     G1   
  18. }   
  19.   
  20. ClassH extends ClassD{   
  21.     H1   
  22. }   
  23.   
  24. ClassB extends DOClass{   
  25.     B1   
  26. }   
  27.   
  28. ClassE extends ClassB{   
  29.     E1,e2,e3,e4,e5,e6   
  30. }   
  31.   
  32. ClassF extends ClassB{   
  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.      < class   name =”ClassA”  table =”TABLE_A”  discriminator-value =”A” >   
  44.          < id />   
  45.          < discriminator   column =”A_TYPE”  type =”string” />   
  46.          < property   name =”a1”  column =”A1” />   
  47.          < sub-class   name =”ClassC”  discriminator-value =”C” >   
  48.              < property   name =”c1”  column =”C1” />   
  49.          </ sub-class >   
  50. < subclass   name =”ClassD”  discriminator-value =”D” >   
  51.              < property   name =”d1”  column =”D1” />   
  52.              < subclass   name =”ClassG”  discriminator-value =”G” >   
  53.                  < property   name =”g1”  column =”G1” />   
  54.              </ subclass >   
  55.              < subclass   name =”ClassH”  discriminator-value =”H” >   
  56.                  < property   name =”h1”  column =”H1” />   
  57.              </ subclasss >   
  58. </ subclass >   
  59. </ class >   
  60. </ hibernate-mapping >   
  61. ClassB.hbm.xml   
  62. < hibernate-mapping >   
  63.      < class   name =”ClassB”  table =”TABLE_B” >   
  64.          < id />   
  65.          < property   name =”b1”  column =”B1” />   
  66.          < joined-subclass   name =”ClassE”  table =”TABLE_E” >   
  67.              < key   column =”B_ID” />   
  68.              < property   name =”e1”  column =”E1” />   
  69.              < property   name =”e2”  column =”E2” />   
  70.              < property   name =”e3”  column =”E3” />   
  71.              < property   name =”e4”  column =”E4” />   
  72.              < property   name =”e5”  column =”E5” />   
  73.              < property   name =”e6”  column =”E6” />   
  74.          </ joined-subclass >   
  75.          < joined-subclass   name =”ClassF”  table =”TABLE_F” >   
  76.              < key   column =”B_ID” />   
  77.              < property   name =”f1”  column =”F1” />   
  78.              < property   name =”f2”  column =”F2” />   
  79.              < property   name =”f3”  column =”F3” />   
  80.              < property   name =”f4”  column =”F4” />   
  81.              < property   name =”f5”  column =”F5” />   
  82.              < property   name =”f6”  column =”F6” />   
  83.              < property   name =”f7”  column =”F7” />   
  84.          </ joined-subclass >   
  85.      </ class >   
  86. </ hibernate-mapping >   

5、映射Bag,List和Map

IDBag

代码
  1. IMAGES{ID(PK),CUSTOMER_ID(FK),FILENAME}   
  2. List  images  =  new  ArrayList();   
  3. Customer.hbm.xml   
  4.   
  5. < idbag   name =”images”  table =”IMAGES”  lazy =”true” >   
  6.      < collection-id   type =”long”  column =”ID” >   
  7.          < generator   class =”increment” />   
  8.      </ collection-id >   
  9.      < key   column =”CUSTOMER_ID” />   
  10.      < element   column =”FILENAME”  type =”string”  not-null =”true” />   
  11. </ idbag >   

List

代码
  1. IMAGES{CUSTOMER_ID(PK/FK),POSITION(PK),FILENAME}   
  2. List  images  =  new  ArrayList();   
  3. Customer.hbm.xml   
  4. < list   name =”images”  table =”IMAGES”  lazy =”true” >   
  5.      < index   column =”POSITION” />   
  6.      < key   column =”CUSTOMER_ID” />   
  7.      < element   column =”FILENAME”  type =”string”  not-null =”true” />   
  8. </ list >   

Map

代码
  1. IMAGES{CUSTOMER_ID(PK/FK),IMAGE_NAME(PK),FILENAME}   
  2. Map  images  =  new  HashMap();   
  3. < map   name =”images”  table =”IMAGES”  lazy =”true” >   
  4.      < key   column =”CUSTOMER_ID” />   
  5. < index   column =”IMAGE_NAME”  type =”string” />   
  6.      < element   column =”FILENAME”  type =”string”  not-null =”true” />   
  7. </ map >   
  8.   
  9. Set idbag map 支持数据库排序  order  by  =”ID”   
  10. Set map 支持内存排序   sort  = “MyComparator”  

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

代码
  1. Public  class  Customer{   
  2.     Address homeAddress;   
  3.     Address comAddress;   
  4. }   
  5.   
  6. Customer.hbm.xml   
  7. <many-to-one name=”homeAddress”  class =”Address” column=”HOME_ADDRESS_ID” cascade=”all” unique=” true ”/>   
  8. <many-to-one name=”comAddress”  class =”Address” column=”COM_ADDRESS_ID” cascade=”all” unique=” true ”/>   
  9.   
  10. Address.hbm.xml   
  11. <one-to-one name=”address”  class =”Customer” property-ref=”homeAddress”/>  

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

代码
  1. Customer.hbm.xml   
  2. < one-to-one   name =”address”  class =”Address”  cascade =”all” />   
  3. Address.hbm.xml   
  4. < class   name =”address” >   
  5.      < id >   
  6.          < generator   class =”foreign” >   
  7.              < param   name =”property” > customer </ param >   
  8.          </ generator >   
  9.      </ id >   
  10. < one-to-one   name =”customer”  class =”Customer”  constrained =”true” />   
  11. </ class >   

7、映射一对多关联

代码
  1. < class   name = "Person" >   
  2. < id   name = "id"   column = "personId" >   
  3.          < generator   class = "native" />   
  4. </ id >   
  5. < many-to-one   name = "address"   column = "addressId"   not-null = "true" />   
  6. </ class >   
  7.   
  8. < class   name = "Address" >   
  9. < id   name = "id"   column = "addressId" >   
  10. < generator   class = "native" />   
  11. </ id >   
  12. < set   name = "people"   inverse = "true" >   
  13.        < key   column = "addressId" />   
  14. < one-to-many   class = "Person" />   
  15. </ set >   
  16. </ class >   

8、映射多对多关联

代码
  1. < set   name =”items”  table =”CATEGORY_ITEM”  lazy =”true”  cascade =”save-update” >   
  2.      < key   column =”CATEGORY_ID” >   
  3.      < many-to-many   class =”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缓存
Select c.ID,c.Name,c.age,o.ORDER_NUM,o.CUSTOMER_ID from Customer c,inner join c.orders c 除外。

SessionFactory缓存(二级缓存)

代码
  1. < class   name =”Category”  table =”CATEGORYS” >   
  2.      < cache   usage =”read-write” />   
  3.      < id />   
  4.      < set   name =”items”  inverse =”true”  lazy =”true” >   
  5.          < cache   usage =”read-write” />   
  6.          < key />   
  7.      </ set >   
  8. </ class >   
  9. < class   name =”Item” >   
  10.      < cache   usage =”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.      < diskStore   path =”c:\\temp” />   
  20.      < defaultCache   
  21.          maxElementsInMemory =”10000”   
  22.          eternal =”false”   
  23.          timeToIdleSeconds =”120”   
  24.          timeToLiveSeconds =”120”   
  25.          overflowToDisk =”true” />   
  26.      < cache   name =”Category”   
  27.          maxElementsInMemory =”10000”   
  28.          eternal =”false”   
  29.          timeToIdleSeconds =”120”   
  30.          timeToLiveSeconds =”120”   
  31.          overflowToDisk =”true” />   
  32.   
  33.      < cache   name =”Category.Items”   
  34.          maxElementsInMemory =”10000”   
  35.          eternal =”false”   
  36.          timeToIdleSeconds =”120”   
  37.          timeToLiveSeconds =”120”   
  38.          overflowToDisk =”true” />   
  39.   
  40.      < cache   name =”Item”   
  41.          maxElementsInMemory =”10000”   
  42.          eternal =”false”   
  43.          timeToIdleSeconds =”120”   
  44.          timeToLiveSeconds =”120”   
  45.          overflowToDisk =”true” />   
  46.   
  47.      < cache   name =”customerQueries”…. />  <!—设置查询缓存   
  48.   
  49. </ ehcache >   

Query q = session.createQuery();
q.setCacheable(true);
q.setCacheRegion(“customerQueries”);

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

直接调用JDBC API不会使用任何缓存。
二级缓存适合查询较多但是很少更新的情况。

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

五、临时对象(Transient Object)、持久对象(Persistent Object)和游离对象(Detached Object)
临时对象:表示对象的主键不存在(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-one name=”customer” class=”Customer” constrained=”true”/>
HQL会忽略迫切左外连接检索和lazy(只有load才为代理对象)策略。
Session.find(“from Customer c as c left join fetch c.orders where c.id=1”)

Hibernate的检索方式
HQL、NativeSql和QBC
From Customer c inner join c.orders o 查询结果保存到session缓存
Select c.ID,c.Name,c.age,o.ORDER_NUM,o.CUSTOMER_ID from Customer c,inner join c.orders c查询结果不存入Session缓存。

七、Hibernate并发控制
乐观锁:VERSION或者timestamp控制,session.lock()立刻进行版本检查,session.update(),update的时候执行版本检查。
悲观锁:select for upload,session.get(Customer.class,new Long(1),LockMode.UPGRADE)

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

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

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

http://www.javaeye.com/topic/42854



posted on 2007-01-22 15:11 java_蝈蝈 阅读(608) 评论(0)  编辑  收藏 所属分类: HIBERNATE

只有注册用户登录后才能发表评论。


网站导航: