zoukankan      html  css  js  c++  java
  • Spring事务管理学习

    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///testspring
    jdbc.username=root
    jdbc.password=root

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


    这里使用xml配置来声明事务

    准备好jar包



    在数据库中创建数据:

    #创建数据表account 
    CREATE TABLE `account` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(20) NOT NULL,
      `money` double DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    INSERT INTO `account` VALUES ('1', 'aaa', '1000');
    INSERT INTO `account` VALUES ('2', 'bbb', '1000');
    INSERT INTO `account` VALUES ('3', 'ccc', '1000');

    创建,applicationContext.xml,jdbc.properties,log4j.properties 等会儿再配置



    创建一个转账业务接口和实现类,再对应的dao层的接口和实现类:

    package com.guoke;
    /**
     *转账业务接口
     */
    public interface AccountService {
    <span style="white-space:pre">	</span>public void transfer(String out, String in, double money);
    }
    
    package com.guoke.spring.demo1;
    import com.guoke.AccountDao;
    import com.guoke.AccountService;
    
    /**
     *转账业务的实现类
     */
    public class AccountServiceImpl implements AccountService {
    	
    	private AccountDao accountDao;
    	
    	public void setAccountDao(AccountDao accountDao) {
    		this.accountDao = accountDao;
    		System.out.println("初始化accountDao"+accountDao);
    	}
    
    	@Override
    	public void transfer(String out, String in, double money) {
    		accountDao.outMoney(out, money);
    		accountDao.inMoney(in, money);
    	}
    
    }
    
    package com.guoke;
    
    
    /**
     *dao层接口
     */
    public interface AccountDao {
    <span style="white-space:pre">	</span>public void inMoney(String in,Double money);
    <span style="white-space:pre">	</span>public void outMoney(String out,Double money);
    }
    
    package com.guoke.spring.demo1;
    
    
    import org.springframework.jdbc.core.support.JdbcDaoSupport;
    
    
    import com.guoke.AccountDao;
    
    
    /**
     *dao层的实现类
     */
    public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
    
    
    <span style="white-space:pre">	</span>@Override
    <span style="white-space:pre">	</span>public void inMoney(String in, Double money) {
    <span style="white-space:pre">		</span>String sql="update account set money=money+? where name=?";
    <span style="white-space:pre">		</span>this.getJdbcTemplate().update(sql,money,in);
    <span style="white-space:pre">	</span>}
    
    
    <span style="white-space:pre">	</span>@Override
    <span style="white-space:pre">	</span>public void outMoney(String out, Double money) {
    <span style="white-space:pre">		</span>String sql="update account set money=money-? where name=?";
    <span style="white-space:pre">		</span>this.getJdbcTemplate().update(sql, money,out);
    <span style="white-space:pre">		</span>
    <span style="white-space:pre">	</span>}
    
    
    }
    


    然后配置文件:


    applicationContext.xml   :

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    <span style="white-space:pre">	</span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    <span style="white-space:pre">	</span>xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    <span style="white-space:pre">	</span>xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx.xsd">
    <span style="white-space:pre">	</span><!-- 引入外部的属性文件 -->
    <span style="white-space:pre">	</span><context:property-placeholder location="classpath:jdbc.properties"/>
    <span style="white-space:pre">	</span><!-- 引入c3p0连接池 -->
    <span style="white-space:pre">	</span><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <span style="white-space:pre">		</span><property name="driverClass" value="${jdbc.driverClass}" />
    <span style="white-space:pre">		</span><property name="jdbcUrl" value="${jdbc.url}" />
    <span style="white-space:pre">		</span><property name="user" value="${jdbc.username}" />
    <span style="white-space:pre">		</span><property name="password" value="${jdbc.password}" />
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!-- 引入dao层类 -->
    <span style="white-space:pre">	</span><bean id="accountDao" class="com.guoke.spring.demo1.AccountDaoImpl">
    <span style="white-space:pre">		</span><property name="dataSource" ref="dataSource" />
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!-- 引入业务层类 -->
    <span style="white-space:pre">	</span><bean id="accountService" class="com.guoke.spring.demo1.AccountServiceImpl">
    <span style="white-space:pre">		</span><property name="accountDao" ref="accountDao" />
    <span style="white-space:pre">	</span></bean>
    
    
    </beans>
    jdbc.properties   :

    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///testspring
    jdbc.username=root
    jdbc.password=root
    

    注意:这里的testspring是自己建的数据库的名字

    log4j.properties  :

    log4j.rootLogger=DEBUG, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.logger.org.apache=INFO

    最后再创建一个转账的测试类


    package com.guoke.demo1;
    
    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;
    import com.guoke.AccountService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo1 {
    	@Resource(name="accountService")
    	private AccountService accountService;
    	
    	@Test 
    	public void demo1(){
    		accountService.transfer("aaa","bbb", 200d);
    	}
    }
    

    测试后, 得到的效果: 


    现在是正常情况。。


    由于这里没有开启事务,如果在转账过程中出错,那么就不一定有上面的效果。

    先手动添加一个异常:

    	public void transfer(String out, String in, double money) {
    		accountDao.outMoney(out, money);
    		int i=1/0;//运行时抛出异常
    		accountDao.inMoney(in, money);
    	}
    只转出,未转入



    为了管理事务有编程式事务管理,声明式事务管理。


    编程式的事务管理,set注入方式,哪个类需要进行事物控制,就需要在对应的BEAN中注入事物管理模板

     1.在AccountService中使用TransactionTemplate (事务管理的模板)

    2.TransactionTemplate依赖DateSourceTransaction (这是管理数据库的)

    3.DataSourcceTransactionManager依赖DataSource构造


    PlatFormTransactionManager是管理事务的接口


    编程式事务管理:


    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    <span style="white-space:pre">	</span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    <span style="white-space:pre">	</span>xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    <span style="white-space:pre">	</span>xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx.xsd">
    <span style="white-space:pre">	</span><!-- 引入外部的属性文件 -->
    <span style="white-space:pre">	</span><context:property-placeholder location="classpath:jdbc.properties"/>
    <span style="white-space:pre">	</span><!-- 引入c3p0连接池 -->
    <span style="white-space:pre">	</span><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <span style="white-space:pre">		</span><property name="driverClass" value="${jdbc.driverClass}" />
    <span style="white-space:pre">		</span><property name="jdbcUrl" value="${jdbc.url}" />
    <span style="white-space:pre">		</span><property name="user" value="${jdbc.username}" />
    <span style="white-space:pre">		</span><property name="password" value="${jdbc.password}" />
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!-- 引入dao层类 -->
    <span style="white-space:pre">	</span><bean id="accountDao" class="com.guoke.spring.demo1.AccountDaoImpl">
    <span style="white-space:pre">		</span><property name="dataSource" ref="dataSource" />
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!--配置事务管理器 -->
    <span style="white-space:pre">	</span><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <span style="white-space:pre">		</span><property name="dataSource" ref="dataSource"/>
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!-- 配置事务管理的模板,为简化事务管理的代码而提供的类 -->
    <span style="white-space:pre">	</span><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <span style="white-space:pre">		</span><property name="transactionManager" ref="transactionManager"/>
    <span style="white-space:pre">	</span></bean>
    <span style="white-space:pre">	</span><!-- 引入业务层类 -->
    <span style="white-space:pre">	</span><bean id="accountService" class="com.guoke.spring.demo1.AccountServiceImpl">
    <span style="white-space:pre">		</span><property name="accountDao" ref="accountDao" />
    <span style="white-space:pre">		</span><property name="transactionTemplate" ref="transactionTemplate"/>
    <span style="white-space:pre">	</span></bean>
    
    
    </beans>
    
    AccountServiceImpl和SpringDemo1


    package com.guoke.spring.demo1;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallbackWithoutResult;
    import org.springframework.transaction.support.TransactionTemplate;
    import com.guoke.AccountDao;
    import com.guoke.AccountService;
    /**
     *转账业务的实现类
     */
    public class AccountServiceImpl implements AccountService {
    <span style="white-space:pre">	</span>//注入事务管理的模板
    <span style="white-space:pre">	</span>private TransactionTemplate transactionTemplate;
    <span style="white-space:pre">	</span>private AccountDao accountDao;
    <span style="white-space:pre">	</span>
    <span style="white-space:pre">	</span>public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    <span style="white-space:pre">		</span>this.transactionTemplate = transactionTemplate;
    <span style="white-space:pre">	</span>}
    
    
    <span style="white-space:pre">	</span>public void setAccountDao(AccountDao accountDao) {
    <span style="white-space:pre">		</span>this.accountDao = accountDao;
    <span style="white-space:pre">		</span>System.out.println("初始化accountDao"+accountDao);
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>
    <span style="white-space:pre">	</span>@Override
    <span style="white-space:pre">	</span>public void transfer(final String out, final String in, final double money) {
    <span style="white-space:pre">		</span>transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    <span style="white-space:pre">			</span>@Override
    <span style="white-space:pre">			</span>protected void doInTransactionWithoutResult(TransactionStatus status) {
    <span style="white-space:pre">				</span>accountDao.outMoney(out, money);
    <span style="white-space:pre">				</span>//int i=1/0;
    <span style="white-space:pre">				</span>accountDao.inMoney(in, money);
    <span style="white-space:pre">			</span>}
    <span style="white-space:pre">		</span>});
    <span style="white-space:pre">	</span>}
    }
    
    package com.guoke.spring.demo1;
    
    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;
    import com.guoke.AccountService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo1 {
    	@Resource(name="accountService")
    	private AccountService accountService;
    	
    	@Test 
    	public void demo1(){
    		accountService.transfer("aaa","bbb", 200d);
    	}
    }
    

    运行后, 如果有异常, 失败, 则一起失败。,不会出现钱丢失的现象。



    声明式事务管理有三种,这里只写一种。
    基于TransactionProxyFactoryBean的方式
    修改配置文件


    package com.guoke.spring.demo1;
    
    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;
    import com.guoke.AccountService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext2.xml")
    public class SpringDemo1 {
    	@Resource(name="accountService")
    	private AccountService accountService;
    	
    	@Test 
    	public void demo1(){
    		accountService.transfer("aaa","bbb", 200d);
    	}
    }
    

    package com.guoke.spring.demo2;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallbackWithoutResult;
    import org.springframework.transaction.support.TransactionTemplate;
    import com.guoke.AccountDao;
    import com.guoke.AccountService;
    /**
     *转账业务的实现类
     */
    public class AccountServiceImpl implements AccountService {
    	private AccountDao accountDao;
    	public void setAccountDao(AccountDao accountDao) {
    		this.accountDao = accountDao;
    		System.out.println("初始化accountDao"+accountDao);
    	}
    	@Override
    	public void transfer(String out, String in, double money) {
    				accountDao.outMoney(out, money);
    				accountDao.inMoney(in, money);
    	}
    }
    

    package com.guoke.spring.demo2;
    
    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;
    import com.guoke.AccountService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext2.xml")
    public class SpringDemo2 {
    	@Resource(name="accountServiceProxy")
    	private AccountService accountService;
    	
    	@Test 
    	public void demo2(){
    		accountService.transfer("aaa","bbb", 200d);
    	}
    }
    

    效果跟刚才一样的。




    =============================================


    如果报错, 异常信息给的很全, 应该仔细读。


    另外: 之前applicationContext.xml老是 property-placeholder 报错:

    The matching wildcard is strict, but no declaration can be found for element 'context:property-placeholder'

    写好:

     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx.xsd

    以及导包,还是出错。

    后来尝试把xsd改成4.0后,property-placeholder不报错了。



  • 相关阅读:
    Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗
    python四舍五入保留2位小数
    查看python中的keywords(关键字)和modules
    c:forEach实现动态select标签
    解决Windows上数据库密码忘记问题
    Java读取properties文件总结
    URL地址最大长度问题
    Servlet生命周期
    解决mysql 数据库连接密码
    Java中int与integer的区别
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873286.html
Copyright © 2011-2022 走看看