模拟转账操作之半xml半注解版(自定义事务管理)
1、pom.xml依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
2、pojo实体类
package cn.bwm.pojo;
import lombok.Data;
@Data
public class Account {
private Integer id;
private String name;
private Double money;
}
3、Dao层接口
package cn.bwm.dao;
import cn.bwm.pojo.Account;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface AccountDao {
@Select("select * from account where name=#{name}")
Account findByName(@Param("name") String name);
@Update("update account set name=#{name}, money=#{money} where id=#{id}")
void updateAccount(Account account);
}
4、数据源jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis01?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
5、Spring核心配置文件applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="druidDateSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="druidDateSource"/>
<property name="typeAliasesPackage" value="cn.bwm.pojo"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.bwm.dao"/>
</bean>
<context:component-scan base-package="cn.bwm"/>
<aop:aspectj-autoproxy/>
</beans>
6、自定义转账事务管理类
package cn.bwm.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Component
@Aspect
public class TransationManager {
@Autowired
@Qualifier("druidDateSource")
private DataSource dataSource;
private static Connection connection = null;
@PostConstruct
public void init(){
TransactionSynchronizationManager.initSynchronization();
connection = DataSourceUtils.getConnection(dataSource);
}
public void begin(){
System.out.println("1 开启事务......");
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void commit(){
System.out.println("3 提交事务......");
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void rollback(){
System.out.println("4 回滚事务......");
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close(){
System.out.println("5 关闭资源......");
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Around("execution(* cn.bwm.service..*.*(..))")
public Object aroundTransation(ProceedingJoinPoint joinPoint) {
Object result = null;
try {
this.begin();
Object[] args = joinPoint.getArgs();
result = joinPoint.proceed(args);
this.commit();
} catch (Exception e) {
e.printStackTrace();
this.rollback();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
this.close();
}
return result;
}
}
7、Service层接口
package cn.bwm.service;
import cn.bwm.pojo.Account;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface AccountService {
Account findByName(String name);
void updateAccount(Account account);
void transfer(String out,String in,Double money);
}
8、service层接口实现类
package cn.bwm.service.impl;
import cn.bwm.dao.AccountDao;
import cn.bwm.pojo.Account;
import cn.bwm.service.AccountService;
import cn.bwm.util.TransationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
@Qualifier("accountDao")
private AccountDao accountDao;
@Autowired
private TransationManager transationManager;
@Override
public Account findByName(String name) {
return accountDao.findByName(name);
}
@Override
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
@Override
public void transfer(String out, String in, Double money) {
System.out.println("2 转账业务操作开始...");
Account outAccount = accountDao.findByName(out);
System.out.println("转账前"+out+"的账户金额为:"+outAccount.getMoney());
Account inAccount = accountDao.findByName(in);
System.out.println("转账前"+in+"的账户金额为:"+inAccount.getMoney());
outAccount.setMoney(outAccount.getMoney()-money);
inAccount.setMoney(inAccount.getMoney()+money);
accountDao.updateAccount(outAccount);
System.out.println("转账后"+out+"的账户金额为:"+outAccount.getMoney());
accountDao.updateAccount(inAccount);
System.out.println("转账后"+in+"的账户金额为:"+inAccount.getMoney());
}
}
9、测试类
package cn.bwm.service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {
@Autowired
@Qualifier("accountService")
private AccountService accountService;
@Test
public void transfer() {
accountService.transfer("王五","李四",50D);
}
}