Spring4.x❹ Spring的事务管理 DataSourceTransactionManager

版权声明:本文为博主原创文章,未经博主允许不得转载。Q425680992 https://blog.csdn.net/g425680992/article/details/82624441

更多Spring开发在框架开发


1 Spring事务管理?

事务是什么不再多说。Spring事务管理主要用声明式事务管理,通过调用PlatformTransactionManager接口的方式实现,而Spring的事务管理的接口针对dao层框架提供了不同的实现类:(本文主要对传统SpringJDBC方法进行讲解,即下图中的第一个)

这里写图片描述
声明事务的方式有如下两种:

  • 基于XML配置文件实现
  • 基于注解实现

2 Spring 事务管理案例

案例目标: 先向数据库中添加两个用户,然后一个用户向另一个用户进行转帐,将转帐的方法进行事务管理。

项目环境:导入jar包,导入spring相关包(ioc基本包,jdbcTemplate包,aop包),mysql相关包,日志相关包,c3p0相关包。

这里写图片描述

项目数据库创建:

create database db_springTransaction ;
create table tb_user( 
    userId int(20) primary key,
    userName varchar(50) default null,
    userSal decimal(7,2)
);

2.1 实体类

User类

package edu.kmust.user.entity;
import java.math.BigDecimal;
public class User {
    private Integer userId ;
    private String userName;
    private BigDecimal userSal;
    //省略set与get方法   
}

2.2 dao

UserDao类

package edu.kmust.user.dao;
import java.math.BigDecimal;
import org.springframework.jdbc.core.JdbcTemplate;
import edu.kmust.user.entity.User;
/**
 * 持久层User
 * @author zhaoyuqiang
 *
 */
public class UserDao {
    private JdbcTemplate jdbcTemplate ;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    /**
     * 用户少钱,去money的负数
     * @param user
     */
    public void lessMoney(User user,BigDecimal money) {
        String sql = "update tb_user set userSal=userSal+? where userName=?" ;
        int rows = jdbcTemplate.update(sql, 
                money.multiply(new BigDecimal(-1)),user.getUserName());
        System.out.println("少钱成功,影响记录的行数="+rows);
    }
    /**
     * 用户多钱
     * @param user
     */
    public void moreMoney(User user,BigDecimal money) {
        String sql = "update tb_user set userSal=userSal+? where userName=?" ;
        int rows = jdbcTemplate.update(sql, money,user.getUserName());
        System.out.println("多钱成功,影响记录的行数="+rows);
    }
    /**
     * 添加用户
     * @param user
     */
    public void add(User user) {
        String sql = "insert into tb_user values(?,?,?)" ;
        int rows =  jdbcTemplate.update(sql, user.getUserId(),user.getUserName(),user.getUserSal());
        System.out.println("添加用户成功,影响记录的行数="+rows);     
    }
}

2.3 service

UserService类

package edu.kmust.user.service;
import java.math.BigDecimal;
import java.util.List;
import edu.kmust.user.dao.UserDao;
import edu.kmust.user.entity.User;
/**
 * 业务层User
 * @author zhaoyuqiang
 *
 */
public class UserService {
    private UserDao userDao ;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    /**
     * 转帐业务:
     *    一个用户给另一个用户转状,一个用户钱增多,一个用户钱减少
     * @param userList
     */
    public void accountMoney(List<User> userList,BigDecimal money) {
        userDao.lessMoney(userList.get(0),money); 
        userDao.moreMoney(userList.get(1),money);
    }
    /**
     * 添加用户
     * @param user
     */
    public void addUser(User user) {
        userDao.add(user);
    }
}

2.4 Spring配置文件

applicationContext.xml ,Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入一个全面的Spring约束 -->
<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">

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
       <!-- 注入属性 -->
       <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
       <property name="jdbcUrl" value="jdbc:mysql:///db_springTransaction"></property>
       <property name="user" value="root"></property>
       <property name="password" value="root"></property>
    </bean>    
    <bean id="userService" class="edu.kmust.user.service.UserService">
         <property name="userDao" ref="userDao"></property>
    </bean>
    <bean id="userDao" class="edu.kmust.user.dao.UserDao">
       <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">       
       <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

2.5 test

package edu.kmust.user.test;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import edu.kmust.user.entity.User;
import edu.kmust.user.service.UserService;
/**
 * 测试类,测试添加功能与没有事务的转帐
 * @author zhaoyuqiang
 *
 */
public class UserTest {
    @Test
    public void test01() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        //创建两个用户
        User user1 = new User();
        user1.setUserId(1);
        user1.setUserName("黄思");
        user1.setUserSal(new BigDecimal("1000.520"));
        User user2 = new User();
        user2.setUserId(2);
        user2.setUserName("赵玉强");
        user2.setUserSal(new BigDecimal("1000.520"));
        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
        //添加两个用户
        /*userService.addUser(user1);
        userService.addUser(user2);*/
        /*
         * 黄思给我赵玉强转200元
         */
        BigDecimal money = new BigDecimal("200") ;
        userService.accountMoney(userList, money);
    }
}

3 service中的事务管理

上述转账案例不牵扯事务的管理,如果调用减少钱的方法后,因为实际环境出现异常,而不执行后续增加钱的方法,这是不可以的,所以,需要事务管理对转帐业务进行回滚操作。

3.1 XMl配置文件的方式进行事务管理

在spring配置文件中加入事务管理如下,对service中的accountMoney方法进行事务管理,service中不需要进行其他修改

<!-- 事务:第一步,配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入属性dataSource,表明事务管理器要对哪个数据源进行管理  -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 事务:第二步,配置事务增强
            transaction-manager的值与事务管理器的id值一样
     -->
    <tx:advice id="txadvice" transaction-manager="transactionManager">
         <!-- 做事务操作 -->
         <tx:attributes>
             <!-- 设置进行事务操作的方法配置规则,即在哪儿方法里面进行事务操作
                   name:是进行事务操作的方法
                   propagation:是隔离级别,可以不写,这里采用mysql的默认级别
              -->
             <tx:method name="accountMoney*" propagation="REQUIRED"/>
         </tx:attributes>
    </tx:advice>
    <!-- 事务:第三步,配置aop切面 -->
    <aop:config>
         <!-- 切入点 -->
         <aop:pointcut expression="execution(* edu.kmust.user.service.UserService.accountMoney(..))" id="point_accountMoney"/>
         <!-- 切面 ,把哪个增强用在哪个切入点上
               advice-ref: 事务增强的id
               pointcut-ref : 切入点id
         -->
         <aop:advisor advice-ref="txadvice" pointcut-ref="point_accountMoney"/>
    </aop:config>

3.2 注解的方式进行事务管理

使用注解方式比XML配置文件方式要简单多

在spring配置文件中加入事务管理如下

<!-- 事务:第一步,配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入属性dataSource,表明事务管理器要对哪个数据源进行管理  -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--事务注解方式: 第二步,开启事务注解  -->
    <tx:annotation-driven transaction-manager="transactionManager" />

在要使用事务的方法accountMoney所在类UserService上面添加注解

import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserService {
    .....
}        

4本文相关代码参考

https://download.csdn.net/download/g425680992/10659176

猜你喜欢

转载自blog.csdn.net/g425680992/article/details/82624441