Blog信息 |
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7593862 建立时间:2006年5月29日 |

| |
[Hibernate]Hibernate 学习小结 软件技术
lhwork 发表于 2007/1/22 16:48:45 |
一、PO的数据类型设置 int 还是Integer Integer 允许为 null Hibernate
既可以访问Field也可以访问Property,访问Property是只是调用getXXX()、setXXX()方法,因此在from Customer
where c.name=’Tom’ HQL中,name属性不需要存在,只要getName()存在就可以了。
二、Hibernate映射
1、映射复合主键
代码
主键类 Public class CustomerId implements Serializable{
Private final String name; Private final String companyid; } 映射文件 <class name=”test.Customer” table=”CUSTOMERS”> <composite-id name=”customerId” class=”test.CustomerId”> <key-property name=”name” column=”NAME” type=”string”/> <key-property name=”companyId” column=”COMPANY_ID” type=”long”/> </composite-id> <version name=”varsion” column=”VERSION” unsaved-value=”0”/> <many-to-one name=”company” class=”test.Company” column=”COMPANY_ID” insert=”false” update=”false”/> <set name=”orders” lazy=”true” inverse=”true”> <key> <columncolumn=”NAME”/> <columncolumn=”COMPANY_ID”/> </key> </set> </class> <class name=”test.Order” table=”ORDERS”> <many-to-one name=”customer” class=”test.Customer”> <columncolumn=”NAME”/> <columncolumn=”COMPANY_ID”/> </many-to-one> </class> 或 <class name=”test.Customer” table=”CUSTOMERS”> <composite-id name=”customerId” class=”test.CustomerId”> <key-property name=”name” column=”NAME” type=”string”/> <key-many-to-one name=”company” class=”test.Company” column=”COMPANY_ID”/> </composite-id> <version name=”varsion” column=”VERSION” unsaved-value=”0”/> <set name=”orders” lazy=”true” inverse=”true”> <key> <columncolumn=”NAME”/> <columncolumn=”COMPANY_ID”/> </key> </set> </class> <class name=”test.Order” table=”ORDERS”> <many-to-one name=”customer” class=”test.Customer”> <columncolumn=”NAME”/> <columncolumn=”COMPANY_ID”/> </many-to-one> </class>
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对继承、多态,各种复杂的关系都有很好的支持。 |
|
|