首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

hibernate总结

2012-10-10 
hibernate小结一、PO的数据类型设置 int 还是Integer Integer 允许为 null Hibernate 既可以访问Field也可

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

二、Hibernate映射

1、映射复合主键
Java代码 
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=”NAME”/>  
17.            <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=”NAME”/>  
24.            <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=”NAME”/>  
40.            <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=”NAME”/>  
47.            <column=”COMPANY_ID”/>  
48.    </many-to-one>  
49.</class> 


2、映射组成关系
Java代码 
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、映射聚合关系
Java代码 
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、映射继承关系
Java代码 
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
Java代码 
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
Java代码 
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
Java代码 
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、映射一对一关联关系特殊情况一
Java代码 
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”/> 


映射一对一关联关系主键映射
Java代码 
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、映射一对多关联
Java代码 
1.<class name="Person">  
2.<id name="id" column="personId">  
3.        <generator column="addressId" not-null="true"/>  
6.</class>  
7. 
8.<class name="Address">  
9.<id name="id" column="addressId">  
10.<generator inverse="true">  
13.      <key column="addressId"/>  
14.<one-to-many class="Person"/>  
15.</set>  
16.</class> 


8、映射多对多关联
Java代码 
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缓存(二级缓存)
Java代码 
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对继承、多态,各种复杂的关系都有很好的支持。

热点排行