Spring事务管理之编程式事务管理

以转账为例,数据库如下:

首先先要写其service层和dao层,如下所示:

在dao中进行jdbc连接,要继承JdbcDaoSupport,查看其源码可知,只需要进行模板注入或者是连接池(有了连接池之后会进行模板的创建)。

public class TransDaoImpl extends JdbcDaoSupport implements  TransDao{
    /**
     * 转出
     * @param out
     * @param money
     */
    @Override
    public void outMoney(String out, Double money)
     {
        String sql="update trans set money=money-? where name=?";
        this.getJdbcTemplate().update(sql,money,out);
     }

    /**
     * 转入
     * @param in
     * @param money
     */
    @Override
    public void inMoney(String in, Double money) 
    {
        String sql="update trans set money=money+? where name=?";
        this.getJdbcTemplate().update(sql,money,in);
    }
}
public class AccountServiceImpl implements  AccountService {
    /**
     * 注入dao层中的
     */
    private TransDao transDao;
    public void setTransDao(TransDao transDao) {
        this.transDao = transDao;
    }

    //注入事务管理的模板
    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    /**
     * @param out:转出账号
     * @param in:传入账号
     * @param money:交易金额
     */
    @Override
    public void trans(final String out, final String in,final  Double money)
    {
        //对于编程式事务管理  会进行service层代码的改动,所以通常不用编程式事务管理
        /*
        //进行调用
        transDao.inMoney(in,money);
        transDao.outMoney(out,money);
        //这两个事务应该是要么都做 ,要么都不做 transactionTemplate事物管理模板
        */
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            //使用匿名内部类
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) 
            {
                //进行对事物的相应操作
                //匿名内部类使用外部变量的时候  需要将变量变为final
                transDao.inMoney(in,money);

                transDao.outMoney(out,money);
            }
        });

    }
}

再配置其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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation=" http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       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/jee 
       http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-4.0.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 name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置业务层-->
    <bean id="accountService" class="per.hss.trans.AccountServiceImpl">
        <property name="transDao" ref="transDao"/>
        <!--注入事务管理,编程式事物管理需要手动进行事务管理的注入-->
        <property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>

    <!--配置Dao层-->
    <!--这个是将连接池直接进行注入,创建jdbc模板,就不用再dao层进行注入了-->
    <bean id="transDao" class="per.hss.trans.TransDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置事物管理器 ,使用jdbc进行提交的时候connection.setAutoCommit(false)-->
    <bean id="transactionManager"                 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--连接池获得具体连接对象-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事物管理模板 spring为了简化事务管理的代码提供的类-->
    <bean id="transactionTemplate"         
     class="org.springframework.transaction.support.TransactionTemplate">
        <!--将真正进行事物管理的注入-->
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
</beans>

在测试类中进行测试

public class Demo01 
{
    public static void main(String[] args) 
{
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService1=(AccountService) applicationContext.getBean("accountService");
        accountService1.trans("aaa","bbb",50d);
    }

}

用Junit进行测试

@RunWith(SpringJUnit4ClassRunner.class)//配置测试环境
@ContextConfiguration(locations={"classpath:applicationContext.xml"})//引入xml文件
public class Demo01 {

    //测试业务层类,将业务层进行注入
    @Resource(name="accountService")
    private AccountService accountService;
    
    @Test
    public void demo1()
    {
        accountService.trans("aaa","bbb",50d);
    }

}

如果需要测试spring是否进行事务管理,那么就需要在AccountAerviceImpl中作如下改变

transDao.inMoney(in,money);
int i=1/0;
transDao.outMoney(out,money);

对于spring4.2.4需要的是Junit 4.9或以上的版本,否则很可能因为版本冲突导致无法进行测试。

关于编程式事务管理,编程式事务管理需要在每个service层进行改动,所以在一般的开发中不进行使用这种方法。

猜你喜欢

转载自blog.csdn.net/Ysmbdjglww/article/details/81231256
今日推荐