spring事务管理

代码运行环境搭建

spring一系列jar包需要准备齐全

AccountDao.java(接口)

package com.my.spring.transaction.test;

public interface AccountDao {
	
	/**
	 * @param in	:转出账户
	 * @param money	:转出金额
	 */
	public void inMoney(String in,double money);
	
	public void outMoney(String out,double money);
	
}
AccountDaoImpl.java实现类

package com.my.spring.transaction.test;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
	
	@Override
	public void inMoney(String in, double money) {
		String sql = "update account set money = money + ? where username = ?";
		this.getJdbcTemplate().update(sql, money, in);
	}

	@Override
	public void outMoney(String out, double money) {
		String sql = "update account set money = money - ? where username = ?";
		this.getJdbcTemplate().update(sql, money, out);
	}

}
AccountService.java(接口)

package com.my.spring.transaction.test;

public interface AccountService {
	
	/**
	 * @param in	:转出账号
	 * @param out	:转入账号
	 * @param money	:转账金额
	 */
	public void transfer(String in,String out,double money);
	
	
}
AccountServiceImpl.java实现类

package com.my.spring.transaction.test;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class AccountServiceImpl implements AccountService{

	private AccountDao accountDao;
	
	//声明式事务管理
	@Override
	public void transfer(String in, String out, double money) {
		accountDao.outMoney(out, money);
		//int i = 1/0;
		accountDao.inMoney(in, money);
	}
        //spring注入
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
}

spring配置



	
	
	
	
		
		
		
		
		
		
	
	
	
		
	
	
	
		
	
	
	 
	 
	 	
	 
	
TransactionTest.java
package com.my.spring.transaction.test1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @author lhd
 *	案例测试
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-context.xml")
public class TransactionTest {
	
	@Resource(name="accountService")
	private AccountService accountService;
	
	
	@Test
	public void demo1(){
		accountService.transfer("aaa", "bbb", 10);
	}
}


数据库设计
spring事务管理_第1张图片

代码描述:在两个用户之间转账,如果因为一些原因使得代码中途不能继续执行,就可能出现一个用户金额减少,而另一个用户金额未增加,使用org.springframework.jdbc.datasource.DataSourceTransactionManager来管理转账问题,实现转账代码原子性(将转账代码看作一个整体),也就一旦出现转账错误就会事务回滚。举个例子就是在transfer实现方法中两个inMoney和outMoney中加一个i = 1/0,这里出现算数异常就不会向下执行代码,从而使得一个用户转出钱,一个用户没收到钱。

编程式事务管理

编程式事务管理,由java代码实现

spring配置文件修改



	
	
	
	
		
		
		
		
		
		
	
	
	
		
		
	
	
	
		
	
	
	 
	 
	 	
	 
	 
	 
	 
	 	
	 
	
AccountDaoImpl.java需要继承JdbcDaoSupport,这里继承JdbcDaoSupport,再在AccountDaoImpl中注入,由于继承了JdbcDaoSupport,AccountDaoImpl就是自动setJdbcTemplate(),这里就可以使用this.getJdbcTemplate(),然后值sql语句
transactionTemplate中需要注入transactionManager,因为这里事务还是需要交给transactionManager来管理,再将transactionTemplate注入accountService,这里使用org.springframework.transaction.support.TransactionTemplate中的execute方法,具体实现将transfer实现方法修改成

//编程式事务管理
	@Override
	public void transfer(final String in,final String out,final double money) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				accountDao.outMoney(out, money);
				int i = 1/0;
				accountDao.inMoney(in, money);
			}
		});
	}
这样就实现了事务管理,这里如果出错那么事务将会回滚,要么全部执行,要么全部不执行。
这种放修改需要修改java代码,不推荐使用。

基于TransactionProxyFactoryBean的方法

spring配置文件的修改

	

	
	
	
	
		
		
		
		
		
		
	
	
	
		
	
	
	
		
	
	
	 
	 
	 	
	 

	
	
				
		
		
		
		
		
			
				
				PROPAGATION_REQUIRED,+java.lang.ArithmeticException
			
		
	
	
使用org.springframework.transaction.interceptor.TransactionProxyFactoryBean代理的方法来实现事务管理,需要将accountService设置target,也需要注入transactionManager,因为真正管理事务的式transactionManager,还需要配置一个transactionAttributes,prop的key属性,代表accountService中的transfer方法,*号代表通配符。
这里还需要修改的是TransactionTest.java

@Resource(name="accountServiceProxy")
需要注入经过org.springframework.transaction.interceptor.TransactionProxyFactoryBean代理的对象。
* PROPAGATION    : 事务的传播行为
* ISOLATION        : 事务隔离级别
* readOnly        : 只读(不可以修改,添加,删除)
* -Exception    : 发生那些异常回滚
* +Eeception    : 发生那些异常不回滚
这种方法只能单个类配置,不仅配置繁琐,修改起来也不方便,也是不推荐使用的。

基于AspectJ的xml配置

spring配置文件的修改



	
	
	
	
		
		
		
		
		
		
	
	
	
		
	
	
	
		
	
	
	
	 
	 	
	 
	 
	 
	
		
			
		
	
	
	
		
		
		
		
	
	
这里使用首先通过execution(* com.my.spring.transaction.test1.*+.*(..)),让事务管理这些类,表示再com.my.spring.transaction.test包下的类的任意方法的任意参数,其中‘+’代表可以加上子类,最后两点代表任意参数。tx:method中属性:
propagation:事务的传播行为
no-rollback-for:发生那些异常不回滚
rollback-for:发生那些异常回滚
read-only:只读(不可以修改,添加,删除)
timeout:超时数据
这种使用还是很多了,这里配置相对简单,也很清晰。

基于注解的配置



	
	
	
	
		
		
		
		
		
		
	
	
	
		
	
	
	
		
	
	
	
	 
	 	
	 
	 
	
	
这里只需要就可以开启注解驱动。
使用:只需要再业务层使用@Transactional注解就可以了,这个注解可以是类级别的,也可以是方法级别的。

@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void transfer1(String in, String out, double money) {
		accountDao.outMoney(out, money);
		int i = 1/0;
		accountDao.inMoney(in, money);
	}
@Transactional也有很多属性基本和上面那些差不多。
这种使用也比较多,缺点需要修改java代码,优点就是配置简单。










你可能感兴趣的:(web,spring,事务管理)