Spring编程式事物管理的案例

事物管理主要解决一类问题,比如去银行转账,中间出了些故障,导致转账失败,您的钱转过去了,但是对方并没有收到。这样显然不行,所以事物管理就是让事物同时成功或者同时失败。

下面是一个小小的项目从0开始来引导大家说明一下,以eclipse为例。

1. 首先是新建一个dynamic web project:

2.配置相关的jar包 从spring官网弄出来的。此外还要从maven仓库中弄到的mysql连接的jar包。

还需要这几个自行下载吧。

将其导入build path

3.编写代码

AccoutnDAO接口:

package cn.muke.spring.demo1;

import org.springframework.stereotype.Repository;


/** 
 * @ClassName: AccountDAO 
 * @Description: TODO
 * @author: Robert_Wang
 * @date: 2018年8月14日 下午2:38:22  
 */
public interface AccountDAO {
	
	/**
	 * @param out 转出方
	 * @param money 金额
	 */
	public void outmoney(String out, Double money);
	
	/** 
	* @Title: inmoney 
	* @Description: TODO 
	* @param in
	* @param money void
	* @author Robert_Wang
	* @date 2018年8月14日下午2:38:32
	*/ 
	public void inmoney(String in, Double money);
		
}

对应的实现类:

package cn.muke.spring.demo1;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

/**
 * @author asus
 *
 */
/** 
 * @ClassName: AccountDAOImpl 
 * @Description: TODO
 * @author: Robert_Wang
 * @date: 2018年8月14日 下午2:39:06  
 */
public class AccountDAOImpl extends JdbcDaoSupport implements AccountDAO {
	
	
	/* (non Javadoc) 
	 * @Title: outmoney
	 * @Description: TODO
	 * @param out
	 * @param money 
	 * @see cn.muke.spring.demo1.AccountDAO#outmoney(java.lang.String, java.lang.Double) 
	 */ 
	@Override
	public void outmoney(String out, Double money) {
		// TODO Auto-generated method stub
		String sql = "update account set money = money - ? where name = ?";
		this.getJdbcTemplate().update(sql,money,out);
		System.out.println("Transfer out money successfully");
	}

	
	/* (non Javadoc) 
	 * @Title: inmoney
	 * @Description: TODO
	 * @param in
	 * @param money 
	 * @see cn.muke.spring.demo1.AccountDAO#inmoney(java.lang.String, java.lang.Double) 
	 */ 
	@Override
	public void inmoney(String in, Double money) {
		// TODO Auto-generated method stub
		String sql = "update account set money = money + ? where name = ?";
		this.getJdbcTemplate().update(sql,money,in);
		System.out.println("Transfer in money successfully");
		
	}

}

对应实现类:

package cn.muke.spring.demo1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

/** 
 * @ClassName: AccountServiceImpl 
 * @Description: TODO
 * @author: Robert_Wang
 * @date: 2018年8月14日 下午2:40:00  
 */
public class AccountServiceImpl implements AccountService {
	//xml文件中已经将其注入了
	private AccountDAO accountDAO;
	private TransactionTemplate transactionTemplate;
	
	public void setAccountDAO(AccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}

	//注入事物管理的模板
	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	//此处应该用final, 因为该方法new了一个内部类
	/* (non Javadoc) 
	 * @Title: transfer
	 * @Description: TODO该方法即执行事物,要么全部成功,要么全部失败。
	 * @param out
	 * @param in
	 * @param money 
	 * @see cn.muke.spring.demo1.AccountService#transfer(java.lang.String, java.lang.String, java.lang.Double) 
	 */ 
	@Override
	public void transfer(String out, String in, Double money) {
		// TODO Auto-generated method stub
		//执行事物的地方
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
				// TODO Auto-generated method stub
				accountDAO.outmoney(out, money);
//				int i = 1/0;如果执行此句,则发生错误,该方法内部的所有执行都将会失败。
				accountDAO.inmoney(in, money);
				System.out.println("Transfer money successfully");
			}
		});
	}
}

 4.接下来,要在src下面建立一个jdbc.properties和log4j.proeprties。

这里由于隐私的原因,仅展示log4j的文件:

# Configure logging for testing: optionally with log file
log4j.rootLogger=WARN, stdout
# log4j.rootLogger=WARN, stdout, logfile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

 5.这就是学习spring的重点了。

applicationContext.xml配置文件;

<?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:context="http://www.springframework.org/schema/context"  
xmlns:aop="http://www.springframework.org/schema/aop"  
xmlns:tx="http://www.springframework.org/schema/tx"  
xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans.xsd  
http://www.springframework.org/schema/context  
http://www.springframework.org/schema/context/spring-context.xsd  
http://www.springframework.org/schema/aop  
http://www.springframework.org/schema/aop/spring-aop.xsd  
http://www.springframework.org/schema/tx  
http://www.springframework.org/schema/tx/spring-tx.xsd">  
	
	<!--引入外部属性文件-->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!--	配置c3p0连接池-->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property> 
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		
	</bean>
	
	<!--	配置业务层-->
	<bean id="accountService" class="cn.muke.spring.demo1.AccountServiceImpl" >
		
		<property name="accountDAO" ref="accountDAO"/>
		<property name="transactionTemplate" ref="transactionTemplate"/>
		
	</bean>
	
	<!--	配置DAO层-->
	<bean id="accountDAO" class="cn.muke.spring.demo1.AccountDAOImpl">
	<!--	注入连接池-->
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!--	配置事物管理	-->
	<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="transactionManager"/>
		
	</bean>
	
	
	
	
</beans>  

 注意几点:

1)c3p0的连接池那里:properties的name不能变,都是固定的哈,详情可以点击上面的类进去看。

2)DAO里面的注入连接池的dataSource是父类的set方法,所以name也是固定的哈。

3)事物管理的模板的transactionManager同上。

6.最后就是测试了:

package cn.muke.spring.demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//加载核心配置文件
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class SpringDemo1Test {
	
	//注入
	@Resource(name="accountService")
	private  AccountService accountService;
		
	@Test
	public void testDemo1() {
		System.out.println("start");
		accountService.transfer("aaa", "bbb", 200d);
		System.out.println("end");
	}

}

猜你喜欢

转载自blog.csdn.net/qq_40883132/article/details/81666255