事务管理总结

来源:互联网 发布:滴滴算法岗年薪多少 编辑:程序博客网 时间:2024/06/06 02:41

一.JDBC事务管理

JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:
public void setAutoCommit(boolean)
public boolean getAutoCommit()
public void commit()
public void rollback()
java使用JDBC来处理事务的代码:
public int delete(int sID) { dbc = new DataBaseConnection(); Connection con = dbc.getConnection(); try {  con.setAutoCommit(false);// 更改JDBC事务的默认提交方式  dbc.executeUpdate("delete from bylaw where ID=" + sID);  dbc.executeUpdate("delete from bylaw _content where ID=" + sID);  dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID);  con.commit();//提交JDBC事务  con.setAutoCommit(true);// 恢复JDBC事务的默认提交方式  dbc.close();  return 1; } catch (Exception exc) {  con.rollBack();//回滚JDBC事务  exc.printStackTrace();  dbc.close();  return -1; }}


二.Hibernate事务管理

1.在pom.xml添加Hibernate等jar包

 <!-- hibernate4 -->        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-core</artifactId>            <version>4.1.7.Final</version>        </dependency><!--sqlserver驱动包 -->  <dependency>      <groupId>com.microsoft.sqlserver</groupId>      <artifactId>sqljdbc4</artifactId>      <version>4.0</version>  </dependency>  <dependency>      <groupId>commons-dbcp</groupId>      <artifactId>commons-dbcp</artifactId>      <version>1.4</version>  </dependency> <!-- Junit -->        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>            <scope>test</scope>        </dependency>
2.在src目录下编写hibernate.cfg.xml的配置

<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- Database connection settings --><property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property><property name="connection.url">jdbc:sqlserver://172.25.6.146:1433;DatabaseName=xsjdd;SelectMethod=cursor;</property><property name="connection.username">sa</property><property name="connection.password">cosnet</property><!-- SQL dialect --><property name="dialect">org.hibernate.dialect.SQLServerDialect</property><!--将Session扔到线程里去处理,Enable Hibernate's automatic session contextmanagement--><property name="current_session_context_class">thread</property><!-- 在控制台打印SQL语句 --><property name="show_sql">true</property><!-- 自动把实体类与属性映射成数据库中的表与列 --><property name="hbm2ddl.auto">update</property><!-- 自动扫描注解方式配置的hibernate类文件 --><mapping class="com.cosconet.model.User" /></session-factory></hibernate-configuration>
3.编写实体类

package com.cosconet.model;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entity@Table(name = "BD_TestUser", schema = "dbo")public class User implements java.io.Serializable {    // Fields    private String id;    private String name;    private String pwd;    private Date createdatetime;    private Date modifydatetime;    // Constructors    /** default constructor */    public User() {    }    /** minimal constructor */    public User(String id, String name, String pwd) {        this.id = id;        this.name = name;        this.pwd = pwd;    }    /** full constructor */    public User(String id, String name, String pwd, Date createdatetime, Date modifydatetime) {        this.id = id;        this.name = name;        this.pwd = pwd;        this.createdatetime = createdatetime;        this.modifydatetime = modifydatetime;    }    // Property accessors    @Id    @Column(name = "ID", unique = true, nullable = false, length = 36)    public String getId() {        return this.id;    }    public void setId(String id) {        this.id = id;    }    @Column(name = "NAME",nullable = false, length = 100)    public String getName() {        return this.name;    }    public void setName(String name) {        this.name = name;    }    @Column(name = "PWD", nullable = false, length = 32)    public String getPwd() {        return this.pwd;    }    public void setPwd(String pwd) {        this.pwd = pwd;    }    @Temporal(TemporalType.TIMESTAMP)    @Column(name = "CREATEDATETIME", length = 7)    public Date getCreatedatetime() {        return this.createdatetime;    }    public void setCreatedatetime(Date createdatetime) {        this.createdatetime = createdatetime;    }    @Temporal(TemporalType.TIMESTAMP)    @Column(name = "MODIFYDATETIME", length = 7)    public Date getModifydatetime() {        return this.modifydatetime;    }    public void setModifydatetime(Date modifydatetime) {        this.modifydatetime = modifydatetime;    }}
4.编写测试类

package com.cosconet.test;import java.util.Date;import java.util.LinkedList;import java.util.List;import java.util.UUID;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import com.cosconet.model.User;public class TestHibernate {@Testpublic void save(){List<User> list = new LinkedList<User>();        User user = new User();        user.setId(UUID.randomUUID().toString().replaceAll("-", ""));        user.setName("哈宇华帝");        user.setPwd("123");        user.setCreatedatetime(new Date());         list.add(user);        User user1 = new User();        user1.setId(UUID.randomUUID().toString().replaceAll("-", ""));        user1.setName("哈宇华帝1");        user1.setPwd("123");        user1.setCreatedatetime(new Date());         list.add(user1);        Configuration conf = new Configuration().configure();          SessionFactory sf = conf.buildSessionFactory();          Session session = sf.openSession();          Transaction t = session.beginTransaction();//说明一          try{          for(int i=0;i<list.size();i++)        {        User u = list.get(i);        session.save(u);        }            t.commit();//说明二          }catch(Exception e){              t.rollback();              e.printStackTrace();        }finally{              if(session.isOpen()){              session.close();              }          } }}
5.说明一:Hibernate本身没有实现自己的事务管理功能,而是对底层JDBC事务或JTA事务的轻量级封装
org.hibernate.impl.SessionImpl类(该类是会话的实现类):
public Transaction beginTransaction() throws HibernateException {         errorIfClosed();      if ( rootSession != null ) {         log.warn( "Transaction started on non-root session" );      }      Transaction result = getTransaction();      result.begin();      return result;  }     public Transaction getTransaction() throws HibernateException {      errorIfClosed();      return jdbcContext.getTransaction();  }
org.hibernate.jdbc.JDBCContext类:
public Transaction getTransaction() throws HibernateException {      if (hibernateTransaction==null) {         hibernateTransaction = owner.getFactory().getSettings()                .getTransactionFactory().createTransaction( this, owner );      }      return hibernateTransaction;  }  
TransactionFactory有很多实现类:

选择最基本的org.hibernate.transaction.JDBCTransactionFactory观察一下:
public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)throws HibernateException {      return new JDBCTransaction( jdbcContext, transactionContext );  }  
org.hibernate.transaction.JDBCTransaction类的说明:
Transaction implementation based on transaction management through a JDBC Connection.  This the Hibernate's default transaction strategy.  
事务开始时,会禁用自动提交:
public void begin() throws HibernateException {      if (begun) {          return;      }      if (commitFailed) {          throw new TransactionException("cannot re-start transaction after failed commit");      }        log.debug("begin");        try {          toggleAutoCommit = jdbcContext.connection().getAutoCommit();          if ( log.isDebugEnabled() ) {              log.debug("current autocommit status: " + toggleAutoCommit);          }          if (toggleAutoCommit) {              log.debug("disabling autocommit");              jdbcContext.connection().setAutoCommit(false);//关闭事务自动提交          }      }      catch (SQLException e) {          log.error("JDBC begin failed", e);          throw new TransactionException("JDBC begin failed: ", e);      }        callback = jdbcContext.registerCallbackIfNecessary();        begun = true;      committed = false;      rolledBack = false;        if ( timeout>0 ) {          jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);      }        jdbcContext.afterTransactionBegin(this);  } 
打开log日志也能看出很多端倪:

[2013-08-09 16:37:55] DEBUG  -> begin  [2013-08-09 16:37:55] DEBUG  -> opening JDBC connection  [2013-08-09 16:37:55] DEBUG  -> current autocommit status: false  [2013-08-09 16:37:55] DEBUG  -> generated identifier: 1, using strategy: org.hibernate.id.Assigned  [2013-08-09 16:37:55] DEBUG  -> commit  
6.说明二不需要显式的调用flush()方法,事务提交时会根据session的FlushMode自动触发session的flush


还是通过最基本的JDBCTransaction类看一下:

事务提交完成之后又恢复了事务的自动提交

public void commit() throws HibernateException {      if (!begun) {          throw new TransactionException("Transaction not successfully started");      }        log.debug("commit");        if ( !transactionContext.isFlushModeNever() && callback ) {          transactionContext.managedFlush(); //根据FlushMode(通常为AUTO)刷新Session        notifySynchronizationsBeforeTransactionCompletion();      if ( callback ) {          jdbcContext.beforeTransactionCompletion( this );      }        try {          commitAndResetAutoCommit();//在该方法中重新开启了事务自动提交          log.debug("committed JDBC Connection");          committed = true;          if ( callback ) {              jdbcContext.afterTransactionCompletion( true, this );          }          notifySynchronizationsAfterTransactionCompletion( Status.STATUS_COMMITTED );      }      catch (SQLException e) {          log.error("JDBC commit failed", e);          commitFailed = true;          if ( callback ) {              jdbcContext.afterTransactionCompletion( false, this );          }          notifySynchronizationsAfterTransactionCompletion( Status.STATUS_UNKNOWN );          throw new TransactionException("JDBC commit failed", e);      }      finally {          closeIfRequired();      }  }    private void commitAndResetAutoCommit() throws SQLException {      try {          jdbcContext.connection().commit();      }      finally {          toggleAutoCommit();      }  }    private void toggleAutoCommit() {      try {          if (toggleAutoCommit) {              log.debug("re-enabling autocommit");              jdbcContext.connection().setAutoCommit( true );//重新开启事务自动提交          }      }      catch (Exception sqle) {          log.error("Could not toggle autocommit", sqle);          //swallow it (the transaction _was_ successful or successfully rolled back)      }  }
JDBC事务默认自动提交,但是如果Hibernate的事务策略使用JDBC,在事务开始之前,Hibernate会关闭事务自动提交,在事务结束之后,重新开启事务自动提交

7.事务的隔离级别

为了解决多个事务并发会引发的问题。数据库系统提供了四种事务隔离级别供用户选择。
o Serializable:串行化。隔离级别最高
o Repeatable Read:可重复读。
o Read Committed:读已提交数据。
o Read Uncommitted:读未提交数据。隔离级别最差。
数据库系统采用不同的锁类型来实现以上四种隔离级别,具体的实现过程对用户是透明的。用户应该关心的是如何选择合适的隔离级别。
对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,而且具有较好的并发性能。
每个数据库连接都有一个全局变量@@tx_isolation,表示当前的事务隔离级别。JDBC数据库连接使用数据库系统默认的隔离级别。在Hibernate的配置文件中可以显示地设置隔离级别。每一种隔离级别对应着一个正整数。
Read Uncommitted: 1
Read Committed: 2
Repeatable Read: 4
Serializable: 8
在hibernate.cfg.xml中设置隔离级别如下:
    <session-factory>
<!-- 设置JDBC的隔离级别 -->
<property name="hibernate.connection.isolation">2</property>
</session-factory>
设置之后,在开始一个事务之前,Hibernate将为从连接池中获得的JDBC连接设置级别。需要注意的是,在受管理环境中,如果Hibernate使用的数据库连接来自于应用服务器提供的数据源,Hibernate不会改变这些连接的事务隔离级别。在这种情况下,应该通过修改应用服务器的数据源配置来修改隔离级别。


三.spring事务管理

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

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


    根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:

    第一种方式:每个Bean都有一个代理

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /><property name="url" value="jdbc:sqlserver://172.25.6.146:1433;DatabaseName=xsjdd;SelectMethod=cursor;" /><property name="username" value="sa" /><property name="password" value="cosnet" /></bean><!-- 配置sessionFactory --><bean id="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties"><props><!-- web项目启动时是否更新表结构 --><prop key="hibernate.hbm2ddl.auto">update</prop><!-- 系统使用的数据库方言,也就是使用的数据库类型 --><prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop><!-- 是否打印Hibernate生成的SQL到控制台 --><prop key="hibernate.show_sql">true</prop><!-- 是否格式化打印出来的SQL --><prop key="hibernate.format_sql">true</prop></props></property><!-- 自动扫描注解方式配置的hibernate类文件 --><property name="packagesToScan"><list><value>com.cosconet.model</value></list></property></bean><!-- 配置DAO --><bean id="userDao" class="com.cosconet.dao.impl.UserDaoImpl"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 配置service --><bean id="userServiceTarget" class="com.cosconet.service.impl.UserServiceImpl"><property name="userDao" ref="userDao" /></bean><!-- 配置事务管理器 (声明式的事务)--><bean name="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><bean id="userService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 配置事务管理器 --><property name="transactionManager" ref="transactionManager" /><!-- 配置代理类 --><property name="target" ref="userServiceTarget" /><!-- 配置事务属性 --><property name="transactionAttributes"><props><span style="white-space:pre"></span><prop key="*">PROPAGATION_REQUIRED,readOnly</prop><span style="white-space:pre"></span><prop key="delete*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="update*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="add*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="save*">PROPAGATION_REQUIRED</prop></props></property></bean></beans>

第二种方式:所有Bean共享一个代理基类

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /><property name="url" value="jdbc:sqlserver://172.25.6.146:1433;DatabaseName=xsjdd;SelectMethod=cursor;" /><property name="username" value="sa" /><property name="password" value="cosnet" /></bean><!-- 配置sessionFactory --><bean id="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties"><props><!-- web项目启动时是否更新表结构 --><prop key="hibernate.hbm2ddl.auto">update</prop><!-- 系统使用的数据库方言,也就是使用的数据库类型 --><prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop><!-- 是否打印Hibernate生成的SQL到控制台 --><prop key="hibernate.show_sql">true</prop><!-- 是否格式化打印出来的SQL --><prop key="hibernate.format_sql">true</prop></props></property><!-- 自动扫描注解方式配置的hibernate类文件 --><property name="packagesToScan"><list><value>com.cosconet.model</value></list></property></bean><!-- 配置事务管理器 (声明式的事务)--><bean name="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><!-- 代码基类 --><bean id="transactionBase"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"lazy-init="true" abstract="true"><!-- 配置事务管理器 --><property name="transactionManager" ref="transactionManager" /><!-- 配置事务属性 --><property name="transactionAttributes"><props><span style="white-space:pre"></span><prop key="*">PROPAGATION_REQUIRED,readOnly</prop><span style="white-space:pre"></span><prop key="delete*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="update*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="add*">PROPAGATION_REQUIRED</prop><span style="white-space:pre"></span><prop key="save*">PROPAGATION_REQUIRED</prop></props></property></bean><!-- 配置DAO --><bean id="userDao" class="com.cosconet.dao.impl.UserDaoImpl"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 配置service --><bean id="userServiceTarget" class="com.cosconet.service.impl.UserServiceImpl"><property name="userDao" ref="userDao" /></bean><!-- 配置代理--><bean id="userService" parent="transactionBase"><!-- 配置代理类 --><property name="target" ref="userServiceTarget" /></bean></beans>


第三种方式:使用拦截器

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /><property name="url" value="jdbc:sqlserver://172.25.6.146:1433;DatabaseName=xsjdd;SelectMethod=cursor;" /><property name="username" value="sa" /><property name="password" value="cosnet" /></bean><!-- 配置sessionFactory --><bean id="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties"><props><!-- web项目启动时是否更新表结构 --><prop key="hibernate.hbm2ddl.auto">update</prop><!-- 系统使用的数据库方言,也就是使用的数据库类型 --><prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop><!-- 是否打印Hibernate生成的SQL到控制台 --><prop key="hibernate.show_sql">true</prop><!-- 是否格式化打印出来的SQL --><prop key="hibernate.format_sql">true</prop><prop key="current_session_context_class">thread</prop></props></property><!-- 自动扫描注解方式配置的hibernate类文件 --><property name="packagesToScan"><list><value>com.cosconet.model</value></list></property></bean><!-- 配置事务管理器 (声明式的事务)--><bean name="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><!-- 代码基类 --><bean id="transactionBase"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"lazy-init="true" abstract="true"><!-- 配置事务管理器 --><property name="transactionManager" ref="transactionManager" /><!-- 配置事务属性 --><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED,readOnly</prop><prop key="delete*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="add*">PROPAGATION_REQUIRED</prop><prop key="save*">PROPAGATION_REQUIRED</prop></props></property></bean><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor"><property name="transactionManager" ref="transactionManager" /><!-- 配置事务属性 --><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED,readOnly</prop><prop key="delete*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="add*">PROPAGATION_REQUIRED</prop><prop key="save*">PROPAGATION_REQUIRED</prop></props></property></bean><bean id="txProxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="beanNames"><list><value>*Service</value></list></property><property name="interceptorNames"><list><value>transactionInterceptor</value></list></property></bean><!-- 配置DAO --><bean id="userDao" class="com.cosconet.dao.impl.UserDaoImpl"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 配置service --><bean id="userService" class="com.cosconet.service.impl.UserServiceImpl"><property name="userDao" ref="userDao" /></bean></beans>

第四种方式:使用tx标签配置的拦截器

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /><property name="url" value="jdbc:sqlserver://172.25.6.146:1433;DatabaseName=xsjdd;SelectMethod=cursor;" /><property name="username" value="sa" /><property name="password" value="cosnet" /></bean><!-- 配置sessionFactory --><bean id="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties"><props><!-- web项目启动时是否更新表结构 --><prop key="hibernate.hbm2ddl.auto">update</prop><!-- 系统使用的数据库方言,也就是使用的数据库类型 --><prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop><!-- 是否打印Hibernate生成的SQL到控制台 --><prop key="hibernate.show_sql">true</prop><!-- 是否格式化打印出来的SQL --><prop key="hibernate.format_sql">true</prop><prop key="current_session_context_class">thread</prop></props></property><!-- 自动扫描注解方式配置的hibernate类文件 --><property name="packagesToScan"><list><value>com.cosconet.model</value></list></property></bean><!-- 配置事务管理器 (声明式的事务)--><bean name="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" propagation="REQUIRED" read-only="true"/><tx:method name="delete*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="add*" propagation="REQUIRED"/><tx:method name="save*" propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="interceptorPointCuts"expression="execution(* com.cosconet.service.*.*(..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" /></aop:config><!-- 配置DAO --><bean id="userDao" class="com.cosconet.dao.impl.UserDaoImpl"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 配置service --><bean id="userService" class="com.cosconet.service.impl.UserServiceImpl"><property name="userDao" ref="userDao" /></bean></beans>
第五种方式:全注解




报错:org.hibernate.HibernateException: No Session found for current thread
使用spring管理事务后在dao中不再需要调用beginTransaction和commit,也不需要调用session.close(),使用API sessionFactory.getCurrentSession()来替代sessionFactory.openSession()。
采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会。
采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭。
集成hibernate4之后,最小事务级别必须是Required,如果是以下的级别,或者没有开启事务的话,无法得到当前的Session。Java代码:sessionFactory.getCurrentSession();这方法必须在事务控制范围内,否则执行这行代码,会抛出No Session found for current thread。需要把之前一些方法的事务从NOT_SUPPORT提升到required,readonly=true。
<prop key="find*">PROPAGATION_NOT_SUPPORTED,readOnly</prop>改为<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
read-only="true":只读状态时不使用事务






0 0