`
zhangfeiii
  • 浏览: 43293 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Hibernate TransactionManager

阅读更多
hibernate学习笔记3--事务管理
最近在学习hibernate时对dao设计模式产生一些疑惑,总结出以下事务管理方案:
1、只涉及到简单的业务流程(每个业务只涉及一个dao操作)
此时不需要service层,只要dao就够了。
例子:

Java代码
1.public void insertUser(Users user) {  
2.    Session session=SessionFactory.openSession();  
3.    Transaction ts=session.beginTransaction();  
4.    session.save(user);  
5.    ts.commit();  
6.    session.close();  
7.} 
public void insertUser(Users user) {
Session session=SessionFactory.openSession();
Transaction ts=session.beginTransaction();
session.save(user);
ts.commit();
session.close();
}

这里的SessionFactory.openSession()每次都打开一个新的session。session的关闭也可以配置为事务提交后自动关闭:

Xml代码
1.<property name="hibernate.transaction.auto_close_session">true</property> 
<property name="hibernate.transaction.auto_close_session">true</property>


2、业务流程复杂,一个业务中涉及多个dao操作,此时可使用绑定到JDBC事务的方法,还可以使用JTA事务(依赖于容器),也可以选择spring事务拦截器,由spring管理更好,可以从session、事务的管理中解脱出来。

1)将session绑定到JDBC事务上实现:
若一个事务中涉及多个dao操作,就需要将session绑定到JDBC事务,使得当前事务中获取的session都是同一个session,保证事务完整。
使用SessionFactory.getCurrentSession()取得与当前JDBC事务关联的session。
session的打开与关闭无需关心,由hibernate管理。
注意需要配置:

Xml代码
1.<property name="current_session_context_class">thread</property> 
<property name="current_session_context_class">thread</property>
而且在查询时也必须开启一个事务,否则报错。
这样在一个事务中调用多个dao操作,各个dao中的session都是同一个session。
一个包含了多个dao操作的业务层代码如下:

Java代码
1.//模拟转账  
2.public void transfer(){  
3.    Transaction ts=SessionFactory.getCurrentSession().beginTransaction();  
4.    accoutDao.add("accout_A",100);  
5.    accoutDao.add("accout_B",-100);  
6.    ts.commit();  
7.} 
//模拟转账
public void transfer(){
    Transaction ts=SessionFactory.getCurrentSession().beginTransaction();
    accoutDao.add("accout_A",100);
    accoutDao.add("accout_B",-100);
    ts.commit();
}

上面是基于配置方式绑定session到JDBC事务,也可以使用局部线程变量,达到公用同一个session的目的,实现多dao操作的事务管理。此时getSession()方法如下:

Java代码
1.public static Session getSession() throws HibernateException {  
2.        Session session = (Session) threadLocal.get();  
3.        if (session == null || !session.isOpen()) {  
4.            if (sessionFactory == null) {  
5.                rebuildSessionFactory();  
6.            }  
7.            session = (sessionFactory != null) ? sessionFactory.openSession()  
8.                    : null;  
9.            threadLocal.set(session);  
10.        }  
11.        return session;  
12.    } 
public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
        return session;
    }


这样,在一个事务里面不同dao中拿到的session其实是一个session(与当前事务关联),而且查询时不需要开启事务,不需要配置<property name="current_session_context_class">thread</property>。
Demo:
dao层

Java代码
1.public void add(String id,double number) {  
2.    Session s = SessionFactory.getSession();  
3.    Account acc=s.get(Account.Class,id);  
4.    acc.setBalance(acc.getBalance()+number);  
5.    s.update(acc);  
6.} 
public void add(String id,double number) {
    Session s = SessionFactory.getSession();
    Account acc=s.get(Account.Class,id);
    acc.setBalance(acc.getBalance()+number);
    s.update(acc);
}

业务层:

Java代码
1.public void transfer(){  
2.    Transaction ts=SessionFactory.getSession().beginTransaction();  
3.    accoutDao.add("accout_A",100);  
4.    accoutDao.add("accout_B",-100);  
5.    ts.commit();  
6.} 
public void transfer(){
    Transaction ts=SessionFactory.getSession().beginTransaction();
    accoutDao.add("accout_A",100);
    accoutDao.add("accout_B",-100);
    ts.commit();
}

两个dao操作任何一个失败,事务都不会提交(提交之前就发生了异常),保持数据一致。
这样将事务管理放在业务层,dao层只需做原始的CRUD即可,无需关心事务和session。

但是这样有一个明显的缺点:事务失败后需要手动关闭session,因为session配置为自动关闭是当事务正确提交时或者失败回滚时才会自动关闭session(使用getCurrentSession()的不需要这样,但查询也要开启事务)。
所以我们这里再讨论一下spring的事务管理方式,很方便。。。
2)使用Spring实现:
spring配置:

Java代码
1.<bean id="dataSource" 
2.    class="org.springframework.jndi.JndiObjectFactoryBean" destroy-method="close">  
3.        <property name="jndiName">  
4.            <value>java:comp/env/jdbc/pingshen</value>  
5.        </property>  
6.</bean>   
7.      
8.<bean id="sessionFactory" 
9.    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
10.        <property name="dataSource">  
11.            <ref bean="dataSource" />  
12.        </property>  
13.        <property name="hibernateProperties">  
14.            <props>  
15.                <prop key="hibernate.dialect">  
16.                    org.hibernate.dialect.SQLServerDialect  
17.                </prop>  
18.            </props>  
19.        </property>  
20.        <property name="mappingResources">  
21.<list>  
22.         <value>com/cjlu/vo/Users.hbm.xml</value>  
23.</list>  
24.        </property>  
25.    </bean>  
26.    <bean id="hibernateTemplate" 
27.        class="org.springframework.orm.hibernate3.HibernateTemplate" abstract="true">  
28.        <property name="sessionFactory">  
29.            <ref bean="sessionFactory" />  
30.        </property>  
31.    </bean>  
32. 
33.    <bean id="transactionManager" 
34.        class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
35.        <property name="sessionFactory">  
36.            <ref bean="sessionFactory" />  
37.        </property>  
38.    </bean>  
39. 
40.    <!-- 配置事务拦截器 -->  
41.    <bean id="txInterceptor" 
42.        class="org.springframework.transaction.interceptor.TransactionInterceptor">  
43.        <property name="transactionManager" ref="transactionManager" />  
44.        <property name="transactionAttributes">  
45.            <!-- 定义事务传播属性 -->  
46.            <props>  
47.key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
48.                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
49.                <prop key="*">PROPAGATION_REQUIRED</prop>  
50.            </props>  
51.        </property>  
52.    </bean>  
53.    <!-- 配置自动代理 -->  
54.    <bean  
55.        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
56.        <property name="beanNames">  
57.            <list>  
58.                <!-- 这里可以新增要代理的业务bean-->  
59.                <value>userService</value>  
60.            </list>  
61.        </property>  
62.        <property name="interceptorNames">  
63.            <list>  
64.                <value>txInterceptor</value>  
65.            </list>  
66.        </property>  
67.    </bean>  
68.<bean id="userService" 
69.        class="com.cjlu.service.impl.UserServiceImpl">  
70.        <property name="userDao">  
71.            <bean class="com.cjlu.dao.impl.UserDaoImpl" parent="hibernateTemplate">  
72.            </bean>  
73.        </property>  
74.    </bean> 
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean" destroy-method="close">
<property name="jndiName">
<value>java:comp/env/jdbc/pingshen</value>
</property>
</bean>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
         <value>com/cjlu/vo/Users.hbm.xml</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate" abstract="true">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<!-- 配置事务拦截器 -->
<bean id="txInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<!-- 定义事务传播属性 -->
<props>
key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 配置自动代理 -->
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<!-- 这里可以新增要代理的业务bean-->
<value>userService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>txInterceptor</value>
</list>
</property>
</bean>
<bean id="userService"
class="com.cjlu.service.impl.UserServiceImpl">
<property name="userDao">
<bean class="com.cjlu.dao.impl.UserDaoImpl" parent="hibernateTemplate">
</bean>
</property>
</bean>


注意:此时需要spring的IOC(依赖注入),即每个DaoImpl实现类需要继承HibernateDaoSupport类,并在spring配置文件注入hibernateTemplate,为HibernateDaoSupport中的hibernateTemplate属性绑定hibernate模板。

另外,Action中需要注入Service以便调用,不要在DaoImpl中lookup(datasource),以保证事务的完整性。

DaoImpl中从父类HibernateDaoSupport中继承了getSession()方法,只要使用了Spring声明式事务,用完后不需要关闭,DaoImpl只负责原始的数据操作。
分享到:
评论

相关推荐

    hibernate.properties

    ## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager #hibernate.transaction.manager_lookup_class org.hibernate.transaction....

    SpringMVC+Hibernate全注解整合

    &lt;prop key="hibernate.dialect"&gt;${hibernate.dialect} &lt;prop key="hibernate.show_sql"&gt;true &lt;!-- 配置hibernateTemplate --&gt; &lt;bean id="hibernateTemplate" class="org.springframework.orm....

    Spring + Hibernate + Struts 事务配置小例子(带提示框等小技巧)

    前几天搞 Spring + Hibernate + Struts 事务配置 ,网上找了好多资料,不过好无语,大多都是 Ctrl + V,浪费俺的宝贵时间 现在我总结配出一套,给大家参考参考,可能有不足,请大家多多交流。 附:内有弹出...

    用户注册和登录是每个系统的必须存在的一部分,基于Dwr+Struts2+Spring+Hibernate写了一个用户登录注册系统

    29. //不用此包,在启动时招聘:java.lang.NoClassDefFoundError: javax/transaction/TransactionManager 30. jta.jar 31. 32. //Mysql JDBC驱动 33. mysql-connector.jar 34. 35. //Hibernate必须使用,注意...

    spring3.2+strut2+hibernate4

    &lt;bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt; &lt;property name="sessionFactory" ref="sessionFactory" /&gt; &lt;/bean&gt; &lt;!-- JTA环境的事务配置 ...

    ssh(structs,spring,hibernate)框架中的上传下载

     需要指定的是Spring 1.2.5提供了两套Hibernate的支持包,其中Hibernate 2相关的封装类位于org.springframework.orm.hibernate2.*包中,而Hibernate 3.0的封装类位于org.springframework.orm.hibernate3.*包中,...

    spring-jta-narayana:JTA,JPA,Hibernate和Narayana的Spring项目

    添加到applicationContext.xml transactionManager参考并注释旧的transactionManager设置。 在tx:annotation-driven的applicationContext.xml中指示事务管理器。 另外包含:Log4J(根据: ://spring.io/blog/...

    SSH整合&&SSH集成开发

    &lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt; &lt;!-- JTA环境的事务配置 &lt;bean id="transactionManager" class="org.springframework....

    Myeclipse6.0中SSH框架搭建

    class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt; &lt;property name="sessionFactory" ref="sessionFactory"&gt;&lt;/property&gt; &lt;/bean&gt; &lt;!-- 其它Bean定义在此 --&gt; &lt;!-- 定义拦截器 --&gt; ...

    spring五种事务配置demo

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。...

    SSH第7章上机.zip ACCP8.0

    &lt;bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt; &lt;!-- 事务的通知类型 --&gt; &lt;tx:advice id="transactionAdvice" transaction-manager="...

    维生药业小项目 SSH简单学习项目

    &lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.MySQLDialect &lt;prop key="current_session_context_class"&gt;thread &lt;prop key="hibernate.show_sql"&gt;true &lt;prop key="hibernate.format_sql"&gt;...

    Spring事务配置的五种方式

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    Spring事务配置5种方式

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问 时,DataSource实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager。

    Spring事务配置的五种方法

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    ssh框架在application.xml中配置数据源所需jar

    &lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt; &lt;/property&gt; &lt;!-- 配置事务的传播特性 --&gt; ...

    spring-data-projects:测试SpringData整合其他工具的项目

    Spring Data 简介 SpringData提供了针对数据库(包括SQL和NOSQL)的整合方案,对Hibernate JPA、Jedis等工具的api进行高级的封装,为我们提供简单方便地操作接口。...entityManagerFactory、transactionManager

    OA项目SSH整合框架

    &lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt; &lt;property name="sessionFactory" ref="sessionFactory"&gt;&lt;/property&gt; &lt;!-- 配置基于注解的...

    Spring 事务隔离与事务传播的详解与对比

    Spring 事务隔离与事务传播的详解与对比 Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作。... DataSource、 TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进

    SpringMVC-SSH全注解

    &lt;prop key="hibernate.dialect"&gt;${hibernate.dialect} &lt;prop key="hibernate.show_sql"&gt;true &lt;!-- 配置hibernateTemplate --&gt; &lt;bean id="hibernateTemplate" class="org.springframework.orm....

Global site tag (gtag.js) - Google Analytics