Hibernate3.X 实践总结

Hibernate3.X  实践总结
 
Hibernate不是盏省油的灯,也不是想像的射来射去很简单的事。有不少细节处理很差会让你很不舒服的,这方面最突出的表如今两方面:一是事务管理,是JTA事务仍是JDBC事务?幸好有了Spring和J2EE容器;二是胡乱映射,模型关系创建不合理或者错误致使,或者是映射策略和技术不过关致使。这样的最终结果是抛出一堆HibernateException,摸不着头脑。下面是我实践中的一些总结做为备忘录写出来。
 
参考的是最新的Hibernate 3.2.6GA API文档,还吸取了Hibernate牛人(夏新)写的书和翻译中文开发手册的精华。
 
一、Configuration/SessionFactory/Session
Configuration实例表明了一个应用程序中Java类型 到SQL数据库映射的完整集合. Configuration被用来构建一个(不可变的 (immutable))SessionFactory.
SessionFactory是线程安全的,建立代价很高。
Session是非线程安全的,轻量级的。一个Session对应一个JDBC链接,
Session的connection()会获取Session与之对应的数据库链接Connection对象。
Session的功能就是操做对象的,这些对象和数据库表有映射关系。
Session操做的对象是有状态的,分三类:
 
自由状态(transient): 未持久化,未与任何Session相关联,数据库表中没有对应的记录。
持久化状态(persistent): 与一个Session相关联,对应数据库表中一条记录。
游离状态(detached): 已经进行过持久化,但当前未与任何Session相关联,数据库表中曾经有一条记录,如今还有没有就不知道了。
 
游离状态的实例能够经过调用save()、persist()或者saveOrUpdate()方法进行持久化。持久化实例能够经过调用 delete()变成游离状态。经过get()或load()方法获得的实例都是持久化状态的。游离状态的实例能够经过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。游离或者自由状态下的实例能够经过调用merge()方法成为一个新的持久化实例。
 
二、Session的save()/persist()/update()/saveOrUpdate()/merge()/delete()方法
save()方法将指定对象保存,插入表中一条数据;
persist()方法将指定对象保存,插入表中一条数据,我还没发现它和save方法有什么特别之处。
replicate()方法彻底使用给定对象各个属性的值(包括标识id)来持久化给定的游离状态(Transient)的实体,很暴力啊,其中还须要指定存储模式(有四种保存策略供选择)。
update()方法将指定对象更新,更新表中一条数据;
saveOrUpdate()方法接收一个实体对象,根据实体对象的id判断是否已经存在进行保存或更新操做,这样保存和更新方法就统一了;
merge()方法将给定的对象的状态复制到具备相同标识的持久化对象上。
delete()方法将指定对象删除,删除表中一条数据;
 
特别注意:为了使用saveOrUpdate()方法,在由定义映射文件时,经过设定<id>标签的unsaved-value="null"来判断执行什么操做: 当id属性等于unsaved-value的值(在此为null)时,则认为尚未保存,应该执行保存操做,不然执行更新操做。这样设定以后,可使用saveOrUpdate()方法来统一保存和更新的方法。
 
<id name="id" column="id" type="java.lang.Integer" unsaved-value="null">
    <generator class="native"/>
</id>
 
unsaved-value能够设定的值有四个:
any:老是储存
none:老是更新
null:id为null时储存(预设)
valid:id为null或是指定值时储存
 
三、Session的get()/load()方法
get()方法会老是查询实体对象,不存在时候返回null;
load()方法也是获取一个实体对象,不存在时候抛空指针异常。
 
四、Session的clear()/evict()方法
clear()方法清除Session级别缓存中的全部实体(包括各类状态)对象,目的是释放内存。
evict()方法清除Session级别缓存中的指定的实体(包括各类状态)对象。
固然,Session关闭后,这些缓存也就不存在了,会等待JVM回收。
 
五、Session的flush()方法
flush()强制持久化Session缓存中的实体对象。通常还会调用clear()或evict(),目的是赶忙保存,释放宝贵内存资源。
 
六、Session的commit()/rollback()方法
commit()方法用于提交Session上的事务,不然工做单元不会对数据库产生影响。若是执行出现异常(也就是commit()失败了),则以前的操做取消,执行rollback()可撤消以前的操做。
 
七、Session的close()/isOpen()/isConnected()/reconnect()方法
close()方法关闭Session所对应数据库链接,与其相关联的对象生命周期结束。
isOpen()方法检查Session是否仍然打开,若是Session已经断开,则可使用reconnect(Connection connection)来从新让Session关联一个JDBC链接。
isConnected()方法检查当前Session是否处于链接状态。
 
八、Criteria、DetchedCriteria和Query接口
Criteria和Query的实例都是和Session绑定的,其生命周期跟随着Session结束而结束。
DetchedCriteria实例至关于一个SQL模板,目的是为了复用。其中的getExecutableCriteria(session)方法接收一个Session对象,并与之绑定,返回一个Criteria对象。
 
九、Hibernate类的initialize()方法
initialize()方法强制Hibernate当即加载指定实体所关联的对象和集合。Hibernate类中还有其余几个颇有用但不适很经常使用的方法。
 
十、映射文件中的lazy属性
在Hibernate3中,class元素的lazy属性默认是true,若是不须要,则须要显示指定为lazy="false",不然,操做load返回的对象会抛异常。另外Hibernate3中还能够为实体属性指定lazy属性。
 
十二、JDBC事务和JTA事务
Hibernate自己没有事务管理功能,它依赖于JDBC或JTA的事务管理功能,在Hibernate配置文件中,若是不显式指定Transaction的工厂类别属性hibernate.transaction.factory_class的配置,则默认为JDBC事务:
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>。
在经过SessionFactory获取到Session后,与Session相关联的JDBC Connection实例就被设定为false。
 
特别注意:若是数据库不支持事务,好比MySQL的MyISAM引擎的表就不支持事务,声明事务也不会起做用。要使MySQL5的表支持事务,则能够指定表的引擎类型为InnoDB。若是是学习或者研究,目前最好仍是使用PostgreSQL 8.3或DB二、Oracle。
 
JDBC事务老是和一个数据库链接(或一个Session)相关联的。
JTA事务则能够跨越多个数据链接(或多个Session),这些链接还能够是不一样数据库的链接,JTA事务通常由容器进行管理。编程只要在多个操做单元的开始和结束定义JTA事务的边界便可。
 
特别注意:若是使用了JTA事务,则不能再用在JDBC式的事务来管理每一个Session的操做,不然会出错。为了程序的的通用性,通常来讲,都是使用JTA事务来构建应用,这使用任何环境。固然,也可使用事务代理为每一个JDBC的操做方法加入事务控制。这样也为程序之后移植到JTA容器事务上带来很大方便。其实如今可使用Spring的事务管理,与Hibernate结合的很是完美。
 
敬请关注,未完待续。。。
相关文章
相关标签/搜索