spring boot踩过的坑---spring boot事务管理(1)

本文使用spring boot编写一个简单的模拟银行转账的业务;

  • 环境介绍

spring boot版本号:1.5.14

数据库:mysql

  • 引入的依赖

         <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>  
            <groupId>org.mybatis.spring.boot</groupId>  
            <artifactId>mybatis-spring-boot-starter</artifactId>  
            <version>1.3.1</version>  
        </dependency>

  • 项目结构

  • 实体类
package com.ylink.urrp.entity;

import java.math.BigDecimal;

public class Salary {
    private String nane;

    private BigDecimal money;

    public String getNane() {
        return nane;
    }

    public void setNane(String nane) {
        this.nane = nane == null ? null : nane.trim();
    }

    public BigDecimal getMoney() {
        return money;
    }

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

 

  • mapper.java文件
import com.ylink.urrp.entity.Salary;
import java.math.BigDecimal;

public interface SalaryMapper {
 
    Salary findByName(String name);
    
    void updateMoneyByName(String name,BigDecimal money);
}

mapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ylink.urrp.mapper.SalaryMapper">
  <resultMap id="BaseResultMap" type="com.ylink.urrp.entity.Salary">
    <result column="nane" jdbcType="VARCHAR" property="nane" />
    <result column="money" jdbcType="DECIMAL" property="money" />
  </resultMap>
  
  <select id="findByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	select * from salary where nane = #{name}
  </select>
  
  <update id="updateMoneyByName">
  	update salary set money = #{arg1} where nane = #{arg0}
  </update>
</mapper>

 

  • service接口
public interface SalaryService {
	
	public void transferIn(String name,BigDecimal money);
	
	public void transferOut(String name,BigDecimal money);
	
	public void transfer(String inUser,String outUser,BigDecimal money);
}

 

  • service实现类
package com.ylink.urrp.service.impl;

import java.math.BigDecimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ylink.urrp.entity.Salary;
import com.ylink.urrp.mapper.SalaryMapper;
import com.ylink.urrp.service.SalaryService;
@Service
public class SalaryServiceaImpl implements SalaryService {
	
	@Autowired
	SalaryMapper mapper;

	@Override
	@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED) 
	public void transferIn(String name, BigDecimal money) {
		Salary salary = mapper.findByName(name);
		BigDecimal result = salary.getMoney().add(money);
		mapper.updateMoneyByName(name, result);
		//throw new RuntimeException("转入时发生了异常....");
	}

	@Override
	@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED) 
	public void transferOut(String name, BigDecimal money) {
		
		Salary salary = mapper.findByName(name);
		BigDecimal result = salary.getMoney().subtract(money);
		mapper.updateMoneyByName(name, result);
		//throw new RuntimeException("转出时发生了异常....");
	}

	@Override
	@Transactional(rollbackFor=Exception.class) 
	public void transfer(String inUser, String outUser, BigDecimal money) {
		System.out.println("开始执行转出操作...");
		this.transferOut(outUser, money);
		System.out.println("转出操作执行成功...");
		System.out.println("开始执行转入操作...");
		this.transferIn(inUser, money);
		System.out.println("转入操作执行成功...");
	}

}

 

  • 测试类
package com.ylink.urrp.test;

import java.math.BigDecimal;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.ylink.urrp.service.SalaryService;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TransactionTest {
	
	@Autowired SalaryService ss;
	
	@Test
	public void testTrans() {
		BigDecimal money = new BigDecimal(200);
		ss.transfer("admin", "test", money );
	}
	

}

 

  • 程序入口
package com.ylink.urrp;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.ylink.urrp.mapper")
public class TransferApplication {

	public static void main(String[] args) {
		SpringApplication.run(TransferApplication.class, args);
	}
}

 

  • application.properties文件
# mysql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/trems
spring.datasource.username=root
spring.datasource.password=root

#mybatis  
mybatis.type-aliases-package=com.ylink.urrp.entity
mybatis.mapper-locations=com/ylink/urrp/mapper/*.xml

logging.level.com.ylink.urrp.mapper=debug
logging.level.org.springframework.jdbc.datasource=debug

 

  • 建表SQL
CREATE TABLE `salary` (
  `nane` varchar(10) DEFAULT NULL,
  `money` decimal(7,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
  • 踩过的坑

  • 1、数据库建表时使用MyISAM引擎,该引擎不支持事务;
  • 2、transfer方法不使用事务,则transferIn和transferOut都没有事务;
  • 3、transfer开启事务,transferIn和transferOut都使用transfer的事务;也就是说transferIn和transferOut是否开启事务没有影响;Spring 从同一个类中的某个方法调用另一个有注解(@Transactional)的方法时,事务会失效(本例面向接口编程)。
  • 4、默认spring事务只在发生未被捕获的 RuntimeException 时才回滚。换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
展开阅读全文

没有更多推荐了,返回首页