Spring与hibernate整合心得
整合思路
? 我们目前写dao的主要关注点:
? 1.dao中需要管理session的打开与关闭,代码是重复的 (用到了HibernateSessionFactory: hbn自动创建的)
? 2.dao中需要自己管理事务,这样的代码是重复的
? 3.核心代码
? 解决:
? 首先解决session的问题,也就是sessionFactory的创建工作问题
? 其次解决事务问题:
整合流程
一、1.加入struts框架支持
2.加入spring框架支持
3.加入hibernate框架支持
项目中加入了spring框架支持后,加入hibernate的时候会提示是否不使用hibernate.cfg.xml文件,也就是说可以把spring和hibernate的配置文件合成一个,我们还是分开使用,在加入Hibernate的时候不需要创建SessionFactory,我们把创建sessionFactory的工作留给spring来做,让spring把sessionFactory注入到我们的 dao中,这样来解决我们开始面临的第一个问题
即添加SessionFactory
? 在spring配置文件中添加一个:
? New Hibernate SessionFactory,指定Hibernate配置文件,其中存放了Hibernate的连接数据库的信息也就是数据源 (DataSource)
二、Isolation Level(事务隔离等级):
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;
2、REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
4、Read Uncommitted:保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1: Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。
2: non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。
3: phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了7个数据。 Dirty reads non-repeatable reads phantom reads
Serializable 不会 不会 不会
REPEATABLE READ 不会 不会 会
READ COMMITTED 不会 会 会
Read Uncommitted 会 会 会
三、readOnly
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。
四、Timeout 在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。
一个简单的例子
显示所有用户信息
核心代码:
在Spring中诸如sessionFactory来解决代码重用问题,代码如下
<!-- 需要注入一个sessionfactory -->
<bean id="userdao" class="dao.StudentDao">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- sessionFactory由spring创建 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>/WEB-INF/hibernate.cfg.xml</value>
</property>
</bean>
在web.xml文件中注册
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
在ParentDao(dao中主要方法实现的类,调用session的类)中继承HibernateDaoSupport类,就可以解决session重复问题
当ParentDao继承HibernateDaoSupport类后,测试的时候会报错,原因就是没有用到事务,所以我们接下来还要处理事务问题
因为很多方法都用到了事务,所以我们可以用到面向切面编程(AOP)策略,具体参见Spring中AOP的应用小心得
我们这里直接用就是了,采用动态自动代理机制,即可
在Spring 的applicationContact中添加
<!-- 声明事务 -->
<!-- 声明advice,事务,需要注入一个transactionManager -->
<bean id="mytran"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="tm" />
</property>
<!-- 事务的传播特性 required -->
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 声明一个HibernateTransactionManager -->
<bean id="tm"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
这样就简单实现了Spring和Hibernate框架的整合,当然,我用的是MyEclispe5.5+Structs1.2+Spring2+Hibernate3.1版本,牵扯到了包冲突问题,由于篇幅,就不在这里分享了哈,O(∩_∩)O哈哈~
不过偶会再分享日志,来解决这个问题
Ok,Spring和Hibernate整合,就分享完了
不足之处,愿高手指正!!!!
谢谢哈