7.Spring事务处理

目录


Spring专栏目录(点击进入…)


Spring事务处理


事务特性(ACID,4个)

(1)原子性(Atomicity)

事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用

(2)一致性(Consistency)

一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏

(3)隔离性(Isolation)

可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

(4)持久性(Durability)

一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中


Spring事务三个基本类

所谓事务管理:按照给定的事务规则来执行提交或者回滚操作
Spring框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个

(1)TransactionDefinition:给定事务规则
(2)PlatformTransactionManager:执行提交或者回滚操作
(3)TransactionStatus:运行事务的状态


事务管理器(PlatformTransactionManager)

Spring并不直接管理事务,而是提供了多种事务管理器,将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。

所有事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口。通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了

public interface PlatformTransactionManager extends TransactionManager {
	// 由TransactionDefinition得到TransactionStatus对象
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
	// 提交
	void commit(TransactionStatus status) throws TransactionException;
	// 回滚
	void rollback(TransactionStatus status) throws TransactionException;
}

从这里可知具体的具体的事务管理机制对Spring来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、JPA。下面分别介绍各个平台框架实现事务管理的机制。


Java原生API事务(JTA)

如果你没有使用以上所述的事务管理,或者是跨越了多个事务管理源(比如两个或者是多个不同的数据源),你就需要使用JtaTransactionManager:

<bean id="transactionManager"
		class="org.springframework.transaction.jta.JtaTransactionManager">
	<property name="transactionManagerName" value="java:/TransactionManager"/>
</bean>

JtaTransactionManager将事务管理的责任委托给javax.transaction.UserTransaction和javax.transaction.TransactionManager对象,其中事务成功完成通过UserTransaction.commit()方法提交,事务失败通过UserTransaction.rollback()方法回滚。

JDBC事务

如果应用程序中直接使用JDBC来进行持久化,DataSourceTransactionManager会为你处理事务边界。为了使用DataSourceTransactionManager,你需要使用如下的XML将其装配到应用程序的上下文定义中:

<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

实际上,DataSourceTransactionManager是通过调用java.sql.Connection来管理事务,而后者是通过DataSource获取到的。通过调用连接的commit()方法来提交事务,同样,事务失败则通过调用rollback()方法进行回滚。

Hibernate事务

如果应用程序的持久化是通过Hibernate实现的,那么你需要使用HibernateTransactionManager。对于Hibernate,需要在Spring上下文定义中添加如下的<bean>声明:

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

sessionFactory属性需要装配一个Hibernate的session工厂,HibernateTransactionManager的实现细节是它将事务管理的职责委托给org.hibernate.Transaction对象,而后者是从Hibernate Session中获取到的。当事务成功完成时,HibernateTransactionManager将会调用Transaction对象的commit()方法,反之,将会调用rollback()方法。

Java持久化API事务(JPA)

Hibernate多年来一直是事实上的Java持久化标准,但是现在Java持久化API作为真正的Java持久化标准进入大家的视野。如果计划使用JPA的话,那需要使用Spring的JpaTransactionManager来处理事务。需要在Spring中这样配置JpaTransactionManager。

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

JpTransactionManager只需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现)。JpaTransactionManager将与由工厂所产生的JPA EntityManager合作来构建事务。


基本事务属性(TransactionDefinition)

事务定义信息(隔离、传播、超时、只读、回滚)

事务管理器接口PlatformTransactionManager通过getTransaction(TransactionDefinition definition)方法来得到事务,这个方法里面的参数是TransactionDefinition类,这个类就定义了一些基本的事务属性。

TransactionDefinition接口内容

public interface TransactionDefinition {
	int getPropagationBehavior();   //返回事务的传播行为
	int getIsolationLevel(); //返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据
	int getTimeout();     //返回事务必须在多少秒内完成。事务超时
	boolean isReadOnly();//事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的
}

那么什么是事务属性呢?
事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面,如图所示

在这里插入图片描述

1.传播行为

事务的第一个方面是传播行为(propagation behavior)。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。指定一个事务性方法的执行行为
例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行
TransactionDefinition.PROPAGATION_REQUIRED默认值

(1)PROPAGATION_REQUIRED(默认)

当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。默认值

(2)PROPAGATION_REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起

(3)PROPAGATION_SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行

(4)PROPAGATION_NESTED

如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED

(5)PROPAGATION_MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常

(6)PROPAGATION_NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起

(7)PROPAGATION_NEVER

以非事务方式运行,如果当前存在事务,则抛出异常


2.隔离级别

事务的第二个维度就是隔离级别(isolation level)。隔离级别定义了一个事务可能受其他并发事务影响的程度。

指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量(TransactionDefinition.ISOLATION_DEFAULT)

(1)ISOLATION_DEFAULT(默认)

默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED

(2)ISOLATION_READ_UNCOMMITTED

一个事务可以读取另一个事务修改但还没有提交的数据
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复。因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别

(3)ISOLATION_READ_COMMITTED

表示一个事务只能读取另一个事务已经提交的数据。可以阻止脏读,但是幻读或不可重复读仍有可能发生,这也是大多数情况下的推荐值

(4)ISOLATION_REPEATABLE_READ

表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。可以阻止脏读和不可重复读,但幻读仍有可能发生

(5)ISOLATION_SERIALIZABLE

最高隔离级别,所有事务依次逐个执行,这样事务之间就完全不可能产生干扰。它通常是通过完全锁定事务相关的数据库表来实现的,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别


并发事务引起的问题

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。并发虽然是必须的,但可能会导致一下的问题

(1)脏读(Dirty reads)

脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的

(2)不可重复读(Nonrepeatable read)

不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间进行了更新

(3)幻读(Phantom read)

幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。


不可重复读与幻读区别

不可重复读的重点是修改: 同样的条件,读取过的数据,再次读取出来发现值不一样了
在一个事务中前后两次读取的结果并不一致,导致了不可重复读

幻读的重点在于新增或者删除: 同样的条件,,第1次和第2次读出来的记录数不一样

从总的结果来看,似乎不可重复读和幻读都表现为两次读取的结果不一致。但如果从控制的角度来看,两者的区别就比较大。
对于前者, 只需要锁住满足条件的记录。
对于后者, 要锁住满足条件及其相近的记录


3.只读

事务的第三个特性是它是否为只读事务。如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来进行一些特定的优化。通过将事务设置为只读,就可以给数据库一个机会,让它应用它认为合适的优化措施


4.事务超时

指定事务的最大运行时间。使用int指定,单位是秒
为了使应用程序很好地运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源
事务超时就是事务的一个定时器,在特定时间内事务如果没有执行完毕,那么就会自动回滚,而不是一直等待其结束


5.回滚规则

定义了哪些异常会导致事务回滚而哪些不会

默认情况下,事务只有遇到运行期异常时(RuntimeException)才会回滚,而在遇到检查型异常时不会回滚(这一行为与EJB的回滚行为是一致的)
但是可以声明事务在遇到特定的检查型异常时像遇到运行期异常那样回滚。同样,还可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常


事务状态(TransactionStatus)

调用PlatformTransactionManager接口的getTransaction()方法得到的是TransactionStatus接口的一个实现

事务具体运行状态

public interface TransactionStatus{
    boolean isNewTransaction();  // 是否是新的事物
    boolean hasSavepoint();       // 是否有恢复点
    void setRollbackOnly();       // 设置为只回滚
    boolean isRollbackOnly();    // 是否为只回滚
    boolean isCompleted;          // 是否已完成
}

这个接口描述的是一些处理事务提供简单的控制事务执行和查询事务状态的方法,在回滚或提交的时候需要应用对应的事务状态


事务实现

Spring所有事务管理策略类都继承org.springframework.transaction.PlatformTransactionManager接口

编程式事务:侵入到了业务代码里面,但是提供了更加详细的事务管理。
声明式事务:由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现,有助于用户将操作与事务规则进行解耦。

两者不同点
1.声明式事务最大的优点就是不需通过编程的方式而进行管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明,便可将事务规则应用到业务逻辑中
2.声明式事务不足的地方在于,与编程式事务相比,只能作用到方法级别,无法像编程式事务那样可以作用到代码块级别

编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,Spring推荐使用TransactionTemplate。


编程式事务

使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,Spring推荐使用TransactionTemplate

(1)使用TransactionTemplate

使用TransactionTemplate 不需要显式地开始事务,甚至不需要显式地提交事务。这些步骤都由模板完成。但出现异常时,应通过TransactionStatus的setRollbackOnly显式回滚事务
TransactionTemplate的execute()接收一个TransactionCallback实例。Callback也是Spring的经典设计,用于简化用户操作
该接口只有一个doInTransaction方法,那么很简单,可以通过匿名内部类的方式将业务代码放在doInTransaction中

TransactionCallback<T>接口源码

@FunctionalInterface
public interface TransactionCallback<T> {
	@Nullable
	T doInTransaction(TransactionStatus status);
}

Object dolnTransaction(TransactionStatus status)
该方法的方法体就是事务的执行体

采用TransactionTemplate和采用其他Spring模板,如JdbcTempalte和HibernateTemplate是一样的方法。它使用回调方法,把应用程序从处理取得和释放资源中解脱出来。如同其他模板,TransactionTemplate是线程安全的。


1.在具体的SQL语句操作签,实例化它
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
2.然后就是具体的SQL操作,不过写起来有点复杂
transactionTemplate.execute(new TransactionCallback() {
	public Object doInTransaction(TransactionStatus status) {
		// 这里执行SQL的操作
		// 发生异常的时候status.setRollbackOnly(),正常的时候直接返回结果
	}
});
3.如果没有返回值,可以使用TransactionCallbackWithoutResult类。

里面的方法调用一样,只不过用了TransactionCallbackWithoutResult的匿名继承

final JdbcTemplate template = new JdbcTemplate(dataSource);
DataSourceTransactionManager tran = new DataSourceTransactionManager(dataSource);
TransactionTemplate tranTemplate = new TransactionTemplate(tran);
tranTemplate.execute(new TransactionCallback() {
	public Object doInTransaction(TransactionStatus status) {
		int i = 0;
		try {
			template.update("Insert into userinfo(username,password) values('jjj','kkk')");
			template.update("Insert into userinfo(username,password) values('llll','mmm')");
			i = 1;
		} catch (Exception ex) {
			ex.printStackTrace();
			status.setRollbackOnly();  //回滚
			i = 0;
		}
		return new Integer(i);
	}
}
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
	<property name="transactionManager">
		<ref bean="transactionManager"/>
	</property>
</bean>
@Autowired
private TransactionTemplate transactionTemplate;

@Autowired
private PayOrderDao payOrderDAO;

//保存支付订单
protected PayOrder savePayReq(final PayOrder payOrder) {
	PayOrder order = (PayOrder) this.transactionTemplate.execute(
		new TransactionCallback() {
			@Override
			public Object doInTransaction(TransactionStatus status) {}
		}
	);
}

使用TransactionCallback()可以返回一个值。如果使用TransactionCallbackWithoutResult则没有返回值

如果事务的执行体没有返回值,则可以使用TransactionCallbackWithoutResult类的实例。这是个抽象类,不能直接实例化,只能用于创建匿名内部类。它也是TransactionCallback 接口的子接口,该抽象类包含一个抽象方法
void dolnTransactionWithoutResult(TransactionStatus status)
该方法与dolnTransaction 的效果非常相似,区别在于该方法没有返回值,即事务执行体无须返回值


(2)直接使用PlatformTransactionManager

对于PlatformTransctionManager。通常,不直接使用它,而是使用它的实现类DataSourceTransactionManager。

1.实例化的时候,需要用个数据源作参数
2.建立事务的定义,使用DefaultTransactionDefinition类,直接new个新的就可以了
3.调用DefaultTransactionDefinition类的setPropagationBehavior方法,参数是TransactionDefinition的常量,例如PROPAGATION_REQUIRED等
4.在使用到具体的SQL操作之前,创建一个TransactionStatus类的实例: TransactionStatus status = transactionManager.getTransaction(def)
其中,transactionManager是DataSourceTransactionManager类的实例,def是DefaultTransactionDefinition的实例
5.之后使用具体的SQL操作,发生异常了,就使用transactionManager.rollback(status)
6.正常操作的话,就使用transactionManager.commit(status)

JdbcTemplate template = new JdbcTemplate(datasource);
DataSourceTransactionManager tran = new DataSourceTransactionManager(datasource);
// 事务定义类
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 返回事务对象
TransactionStatus status = tran.getTransaction(def);
try {
	template.update("Insert into userinfo(username,password) values('aaaaa','bbbbb')");
	template.update("Insert into userinfo(username,password) values('cccc','ddd')");
	tran.commit(status);
} catch (Exception ex) {
	tran.rollback(status);
}
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
// 定义一个某个框架平台的TransactionManager,如JDBC、Hibernate
dataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // 设置数据源
DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定义事务属性
transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 设置传播行为属性
TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // 获得事务状态

try {
	// 数据库操作
	dataSourceTransactionManager.commit(status);// 提交
} catch (Exception e) {
	dataSourceTransactionManager.rollback(status);// 回滚
}

声明式事务(推荐优先,2种)

建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中
显然声明式事务管理要优于编程式事务管理,这正是Spring倡导的非侵入式的开发方式

(1)声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持
(2)和编程式事务相比,声明式事务唯一不足地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别,但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等

(1)基于tx和aop名字空间的xml配置文件(AOP切面)

使用XML配置方式在实现声明式事务处理时,需要定义事务管理器、事务属性、事务切面。其本质是在AOP基础之上,对指定的业务方法前后进行拦截,在方法开始前就加入一个事务,在方法之后根据执行情况决定提交或回滚

(2)基于@Transactional注解(@Transactional)

显然基于注解的方式更简单易用,更清爽。使用注解则更简单只需要加入事务的业务类或方法前添加@Transactional即可;需要注意的一点,当@Transactional作用在类上时,类中所有public方法都具备该事务属性


Spring事务配置使用(5种)

注:以下配置代码参考自Spring事务配置的五种方式

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

(1)每个Bean都有一个代理

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
	<property name="configLocation" value="classpath:hibernate.cfg.xml"/> 
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
</bean>

<!-- 定义事务管理器(声明式的事务) --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
	<!-- 配置事务管理器 --> 
	<property name="transactionManager" ref="transactionManager" />    
	<property name="target" ref="userDaoTarget" /> 
	<property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
	<!-- 配置事务属性 --> 
	<property name="transactionAttributes"> 
		<props> 
			<prop key="*">PROPAGATION_REQUIRED</prop>
		</props> 
	</property>
</bean>

(2)所有Bean共享一个代理基类

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
	<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
</bean> 

<!-- 定义事务管理器(声明式的事务) --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</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</prop> 
		</props> 
	</property> 
</bean>

<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" parent="transactionBase" > 
	<property name="target" ref="userDaoTarget"/>  
</bean>

(3)使用拦截器

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
	<property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
</bean> 

<!-- 定义事务管理器(声明式的事务) --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean> 

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
	<property name="transactionManager" ref="transactionManager" />
	<!-- 配置事务属性 --> 
	<property name="transactionAttributes"> 
		<props> 
			<prop key="*">PROPAGATION_REQUIRED</prop> 
		</props> 
	</property>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
	<property name="beanNames"> 
		<list> 
			<value>*Dao</value>
		</list>
	</property> 
	<property name="interceptorNames"> 
		<list>
			<value>transactionInterceptor</value> 
		</list>
	</property>
</bean> 

<!-- 配置DAO -->
<bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

(4)使用tx标签配置的拦截器

<context:annotation-config />
<context:component-scan base-package="com.bluesky" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
	<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
</bean>

<!-- 定义事务管理器(声明式的事务) --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="*" propagation="REQUIRED" />
	</tx:attributes>
</tx:advice>

<aop:config>
	<aop:pointcut id="interceptorPointCuts" expression="execution(* com.bluesky.spring.dao.*.*(..))" />
	<aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
</aop:config>

(5)全注解

<context:annotation-config />
<context:component-scan base-package="com.bluesky" />

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
	<property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean> 

<!-- 定义事务管理器(声明式的事务) --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

此时在DAO上需加上@Transactional注解,如下:

@Transactional
@Component("userDao")
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    public List<User> listUsers() {
        return this.getSession().createQuery("from User").list();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值