zoukankan      html  css  js  c++  java
  • Spring事务管理之编程式事务管理

    © 版权声明:本文为博主原创文章,转载请注明出处

    案例:利用Spring的编程式事务管理模拟转账过程

    数据库准备

    -- 创建表
    CREATE TABLE `account`(
    	`id` INT NOT NULL AUTO_INCREMENT,
    	`name` VARCHAR(100)	NOT NULL,
    	`money` DOUBLE DEFAULT 0,
    	PRIMARY KEY (`id`)
    )ENGINE = INNODB DEFAULT CHARSET = UTF8;
    -- 初始化数据
    INSERT INTO account (name, money) VALUES ('张三', 1000);
    INSERT INTO account (name, money) VALUES ('李四', 1000);
    INSERT INTO account (name, money) VALUES ('王五', 1000);
    

    实例

    1.项目结构

    2.pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      
      	<modelVersion>4.0.0</modelVersion>
      	
    	<groupId>org.spring</groupId>
    	<artifactId>SpringTransaction-001</artifactId>
    	<packaging>war</packaging>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>SpringTransaction-001 Maven Webapp</name>
    	<url>http://maven.apache.org</url>
    	
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<spring.verion>4.3.8.RELEASE</spring.verion>
    	</properties>
    	
    	<dependencies>
    		<!-- junit -->
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.12</version>
      			<scope>test</scope>
    		</dependency>
    		<!-- spring-core -->
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-core</artifactId>
    		    <version>${spring.verion}</version>
    		</dependency>
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-beans</artifactId>
    		    <version>${spring.verion}</version>
    		</dependency>
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-context</artifactId>
    		    <version>${spring.verion}</version>
    		</dependency>
    		<!-- spring-dao -->
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-jdbc</artifactId>
    		    <version>${spring.verion}</version>
    		</dependency>
    	    <!-- spring-test -->
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-test</artifactId>
    		    <version>${spring.verion}</version>
    		</dependency>
    		<!-- MySQL -->
    		<dependency>
    		    <groupId>mysql</groupId>
    		    <artifactId>mysql-connector-java</artifactId>
    		    <version>5.1.42</version>
    		</dependency>
    		<!-- C3P0 -->
    		<dependency>
    		    <groupId>com.mchange</groupId>
    		    <artifactId>c3p0</artifactId>
    		    <version>0.9.5.2</version>
    		</dependency>
    	</dependencies>
    	
    	<build>
    	  	<finalName>SpringTransaction-001</finalName>
    	</build>
    	
    </project>
    

    3.jdbc.properties

    jdbc.username=root
    jdbc.password=***
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///spring_transaction?useSSL=true&characterEncoding=UTF-8
    

    4.AccountDao.java

    package org.spring.dao;
    
    /**
     * 转账DAO层接口
     */
    public interface AccountDao {
    
    	/**
    	 * 转出
    	 * 
    	 * @param out
    	 * 				转出账号
    	 * @param money
    	 * 				转出金额
    	 */
    	void outMoney(String out, double money);
    	
    	/**
    	 * 转入
    	 * 
    	 * @param in
    	 * 				转入账号
    	 * @param money
    	 * 				转入金额
    	 */
    	void inMoney(String in, double money);
    	
    }
    

    5.AccountDaoImpl.java

    package org.spring.dao.impl;
    
    import org.spring.dao.AccountDao;
    import org.springframework.jdbc.core.support.JdbcDaoSupport;
    
    /**
     * 转账DAO层实现类
     *
     */
    public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    
    	// 转出
    	public void outMoney(String out, double money) {
    
    		String sql = "update account set money = money - ? where name = ?";
    		this.getJdbcTemplate().update(sql, money, out);
    		
    	}
    
    	// 转入
    	public void inMoney(String in, double money) {
    		
    		String sql = "update account set money = money + ? where name = ?";
    		this.getJdbcTemplate().update(sql, money, in);
    
    	}
    
    }
    

    6.AccountService.java

    package org.spring.service;
    
    /**
     * 转账业务层接口
     *
     */
    public interface AccountService {
    	
    	/**
    	 * 转账
    	 * 
    	 * @param out
    	 * 				转出账号 
    	 * @param in
    	 * 				转入账号
    	 * @param money
    	 * 				转账金额
    	 */
    	void transfer(String out, String in, Double money);
    
    }
    

    7.AccountServiceImpl.java

    package org.spring.service.impl;
    
    import org.spring.dao.AccountDao;
    import org.spring.service.AccountService;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;
    	private TransactionTemplate transactionTemplate;
    	
    	public void setAccountDao(AccountDao accountDao) {
    		this.accountDao = accountDao;
    	}
    
    	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    		this.transactionTemplate = transactionTemplate;
    	}
    
    	// 转账
    	public void transfer(final String out, final String in, final Double money) {
    		
    		transactionTemplate.execute(new TransactionCallbackWithoutResult() {//使用事务进行管理
    			
    			@Override
    			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
    				
    				accountDao.outMoney(out, money);
    				accountDao.inMoney(in, money);
    				
    			}
    			
    		});
    
    	}
    
    }
    

    8.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"
        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">
            
    	<!-- 引入外部的属性文件 -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    	
    	<!-- 配置C3P0连接池 -->
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    		<property name="driverClass" value="${jdbc.driver}"/>
    		<property name="jdbcUrl" value="${jdbc.url}"/>
    		<property name="user" value="${jdbc.username}"/>
    		<property name="password" value="${jdbc.password}"/>
    	</bean>
    	
    	<!-- 配置业务层类 -->
    	<bean id="accountService" class ="org.spring.service.impl.AccountServiceImpl">
    		<!-- 注入DAO -->
    		<property name="accountDao" ref="accountDao"/>
    		<!-- 注入事务管理模板 -->
    		<property name="transactionTemplate" ref="transactionTemplate"/>
    	</bean>
    	
    	<!-- 配置DAO层类 -->
    	<bean id="accountDao" class="org.spring.dao.impl.AccountDaoImpl">
    		<!-- 注入连接池 -->
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    	
    	<!-- 配置事务管理器 -->
    	<bean id="transactionManager" 
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<!-- 注入连接池 -->
    		<property name="dataSource" ref="dataSource"/>	
    	</bean>
        
        <!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 -->
        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        	<!-- 注入事务管理器 -->
        	<property name="transactionManager" ref="transactionManager"/>
        </bean>
        
    </beans>
    

    9.TestAccount.java

    package org.spring.test;
    
    import javax.annotation.Resource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.spring.service.AccountService;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class TestAccount {
    	
    	@Resource(name="accountService")
    	private AccountService accountService;
    	
    	@Test
    	public void testTransfer() {
    		
    		accountService.transfer("张三", "李四", 100d);
    		
    	}
    
    }
    

    10.效果预览

      10.1 正常执行

      10.2 将AccountServiceImpl.java代码修改如下,执行

    package org.spring.service.impl;
    
    import org.spring.dao.AccountDao;
    import org.spring.service.AccountService;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;
    	private TransactionTemplate transactionTemplate;
    	
    	public void setAccountDao(AccountDao accountDao) {
    		this.accountDao = accountDao;
    	}
    
    	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    		this.transactionTemplate = transactionTemplate;
    	}
    
    	// 转账
    	public void transfer(final String out, final String in, final Double money) {
    		
    		transactionTemplate.execute(new TransactionCallbackWithoutResult() {//使用事务进行管理
    			
    			@Override
    			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
    				
    				accountDao.outMoney(out, money);
    				int i = 1 / 0;//手动抛出异常
    				accountDao.inMoney(in, money);
    				
    			}
    			
    		});
    
    	}
    
    }
    

    参考:http://www.imooc.com/video/9331

  • 相关阅读:
    求斐波那契数列的第n项
    八大经典排序算法
    [BZOJ 3083] 遥远的国度
    [BZOJ 3306] 树
    [SCOI 2010] 序列操作
    [AHOI 2013] 差异
    [USACO2006 DEC] Milk Patterns
    [JSOI 2007] 字符加密
    [BZOJ 2588] Count on a tree
    [NOIP 2018 Day1] 简要题解
  • 原文地址:https://www.cnblogs.com/jinjiyese153/p/6908560.html
Copyright © 2011-2022 走看看