spring配置简单事务管理器实现事务管理

ConnectionUtils,
用于获取线程上的连接,使同一service上所有的dao方法公用一个connection发生异常时,可以回滚事务
TransactionManager,
用于管理service层上的方法,按照如下步骤:
1.开启事务
2.执行方法
3.提交事务
4.返回结果
5.回滚事务
6.释放资源

关系:
在这里插入图片描述

bean.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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.c"></context:component-scan>

<!--   配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/cjy"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <bean id="connectionUtil" class="com.c.utils.ConnectionUtil">
        <property name="dataSource" ref="dataSource"/>
    </bean>

<!--    配置accountService-->
    <bean id="accountService" class="com.c.service.impl.AccountServiceImpl">
        <property name="tm">
            <bean class="com.c.utils.TransactionManager">
                <property name="connectionUtil"  ref="connectionUtil"/>
            </bean>
        </property>
    </bean>
<!--  配置accountDao-->
    <bean id="accountDao" class="com.c.dao.impl.AccountDaoImpl">
        <property name="queryRunner">
            <bean class="org.apache.commons.dbutils.QueryRunner"></bean>
        </property>
        <property name="connectionUtil" ref="connectionUtil"/>

    </bean>
</beans>

Account

package com.c.bean;

public class Account {
    private Integer accountId;
    private Integer userId;
    private double money;

    public Account() {
    }

    public Account(Integer accountId, Integer userId, double money) {
        this.accountId = accountId;
        this.userId = userId;
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "accountId=" + accountId +
                ", userId=" + userId +
                ", money=" + money +
                '}';
    }

    public Integer getAccountId() {
        return accountId;
    }

    public void setAccountId(Integer accountId) {
        this.accountId = accountId;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

AccountDaoImpl

package com.c.dao.impl;

import com.c.bean.Account;
import com.c.dao.AccountDao;
import com.c.utils.ConnectionUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import org.springframework.stereotype.Repository;

import java.sql.SQLException;

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    private QueryRunner queryRunner;
    private ConnectionUtil connectionUtil;//用于获取线程池上的连接,而不是每次自动获取

    public void setQueryRunner(QueryRunner queryRunner) {
        this.queryRunner = queryRunner;
    }

    public void setConnectionUtil(ConnectionUtil connectionUtil) {
        this.connectionUtil = connectionUtil;
    }

    public Account findAccount(Integer id1) throws SQLException {
        return queryRunner.query(connectionUtil.getCurrentConnection(),"select * from account where accountId=?",new BeanHandler<Account>(Account.class),id1);
    }

    public void updateAccount(Account account1) throws SQLException {
        queryRunner.update(connectionUtil.getCurrentConnection(),"update account set money=? where accountId =?",account1.getMoney(),account1.getAccountId());
    }
}

AccountServiceImpl

package com.c.service.impl;

import com.c.bean.Account;
import com.c.dao.AccountDao;
import com.c.service.AccountService;
import com.c.utils.TransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;

@Service("accountService")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    private TransactionManager tm;

    public void setTm(TransactionManager tm) {
        this.tm = tm;
    }

    public void transferMoney(Integer id1, Integer id2) throws SQLException {
        try {
            //1.开启事务
            tm.begin();
            //2.执行方法
            Account account1=accountDao.findAccount(id1);
            Account account2=accountDao.findAccount(id2);
            account1.setMoney(account1.getMoney()-100);
            account2.setMoney(account2.getMoney()+100);
            accountDao.updateAccount(account1);
            int i=10/0;
            accountDao.updateAccount(account2);
            //3.提交事务
            tm.commit();
            //4.返回结果
            System.out.println("转账成功");
        } catch (SQLException e) {
            //5.异常时回滚事务
            tm.rollback();
            e.printStackTrace();
        } finally {
            //6.释放资源
            tm.release();
        }
    }

}

ConnectionUtil

package com.c.utils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 用于获取线程池上的连接
 */
public class ConnectionUtil {
    //定义用于绑定连接的线程
    private ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();
    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Connection getCurrentConnection() throws SQLException {
        //从线程中获取连接
        Connection connection=threadLocal.get();
        if(connection==null){
            connection=dataSource.getConnection();
            //在线程中存储新获得的连接
            threadLocal.set(connection);
        }
        return connection;
    }

    //把连接和线程池解绑
    public void remove(){
        threadLocal.remove();
    }
}

TransactionManager

package com.c.utils;

import java.sql.SQLException;

/**
 * 用于配置service层的事务管理器
 * 包括事务的开启,提交,回滚,释放资源
 */
public class TransactionManager {
    private ConnectionUtil connectionUtil;

    public void setConnectionUtil(ConnectionUtil connectionUtil) {
        this.connectionUtil = connectionUtil;
    }

    //开启事务
    public void begin() throws SQLException {
        connectionUtil.getCurrentConnection().setAutoCommit(false);
    }

    //提交事务
    public void commit() throws SQLException {
        connectionUtil.getCurrentConnection().commit();
    }

    //回滚事务
    public void rollback() throws SQLException {
        connectionUtil.getCurrentConnection().rollback();
    }

    //释放资源
    public void release() throws SQLException {
        //关闭连接
        connectionUtil.getCurrentConnection().close();
        //把线程和连接解绑
        connectionUtil.remove();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值