Hibernate小结

一、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=”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、映射组成关系

 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对继承、多态,各种复杂的关系都有很好的支持。

posted on 2008-06-13 20:37 Hiro 阅读(209) 评论(0)  编辑  收藏 所属分类: hibernate

<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

留言簿

文章分类(23)

文章档案(23)

搜索

积分与排名

最新评论