![](https://img.haomeiwen.com/i23388588/f98202e4c40f10fe.jpeg)
WHAT ?
我们先来说说 , 什么是正确的转账 . 单纯的sql 语句是不能实现事务处理的 , 需要加上事务处理才能保证转账的成功和失败 .
WHY ?
为什么这么说呢 ? 如果 转账过程中出现错误或者中止程序 , 难不成钱还要继续转过去吗 ? 这时应该出现 事务回滚才是 .
那么 , 我们接下来就来 看看转账案例 !
首先我们来分析一下 , 要怎么去实现 ? ( 做什么事都要做好准备 ! )
思路分析 :
- 明需求 -->2. 建项目 -->3.备好 需要 添加的依赖和插件 -->4.类设计 -->5.编写Mapper接口 和 Mapper.xml -->6.编写测试类
废话不多说 , 那我们开始吧 !
添加 依赖和插件 |||
<dependencies> <!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
<scope>runtime</scope>
</dependency> <!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency> <!-- MyBatis 相关 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency> <!-- Spring 集成 MyBatis 的依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency> <!-- Spring 相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency> <!-- 测试相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.8.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- web 项目共用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency> <!-- 页面标签 -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port> <!-- 端口 -->
<path>/</path> <!-- 上下路径 -->
<uriEncoding>UTF-8</uriEncoding> <!-- 针对 GET 方式乱码处理 -->
</configuration>
</plugin>
</plugins>
</build>
准备好数据库 |||
这是一张 账户模拟表
CREATE TABLE `account` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `balance` decimal(10,2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
编写实体类 |||
@Getter
@Setter
public class Account {
private Long id;
private BigDecimal balance;
}
编写Mapper接口 和 Mapper.xml
public interface AccountMapper {
//加钱
void addBalance(@Param("inId") Long inId, @Param("amount") BigDecimal amount);
//减钱
void subtractBalance(@Param("oldId") Long oldId, @Param("amount") BigDecimal amount);
}
<mapper namespace="cn.wolfcode.mapper.AccountMapper">
<update id="addBalance">
update account SET balance=balance + #{amount} where id=#{inId}
</update>
<update id="subtractBalance">
update account SET balance=balance - #{amount} where id=#{oldId}
</update>
</mapper>
到了这里 , 我们要写 service 要写impl 了吗 ? ( 必须看完这段 , 否则你都不知 why ? )
我们要 用到 MyBatis 框架 的 sqlSessionFactory , 而且我们只需要一个 , 那么我们把 创建sqlSessionFactory就交给Spring 管理好了 . 那么 问题 又来了, 创建 sqlSessionFactory 又需要什么? 数据源 datasource . 那我们就先创建好 datasource , 然后在datasource的基础上 创建sqlSessionFactory .
这里 我们可以关联 db.properties 文件
<!--配置 db.properties-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--配置 DataSource-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--配置别名-->
<property name="typeAliasesPackage" value="cn.wolfcode.domain"></property>
</bean>
<!--*****************************************************************************************-->
<!--配置 AccountMapper接口-->
<!--<bean id="accountMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">-->
<!--<!–借 sqlSessionFactory 来创建–>-->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>-->
<!--<!–具体创建 什么接口类型的代理对象–>-->
<!--<property name="mapperInterface" value="cn.wolfcode.mapper.AccountMapper"></property>-->
<!--</bean>-->
<!--*****************************************************************************************-->
<!--批量创建 Mapper 接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.wolfcode.mapper"></property>
</bean>
<context:component-scan base-package="cn.wolfcode.service.impl"/>
service
public interface IAccountService {
//转账方法
void transfer(Long oldId, Long inId, BigDecimal amount);
}
@Service
@Transactional//事务注解
public class AccountServiceImpl implements IAccountService {
@Autowired
private AccountMapper accountMapper;
public void setAccountMapper(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
@Override
public void transfer(Long oldId, Long inId, BigDecimal amount) {
accountMapper.addBalance(oldId, amount);
//int i=1/0;
accountMapper.subtractBalance(inId, amount);
}
@Override
public void delete(Long id) {
accountMapper.delete(id);
}
}
使用注解配置事务
@Service
@Transactional//事务注解
public class AccountServiceImpl implements IAccountService {
@Autowired
private AccountMapper accountMapper;
public void setAccountMapper(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
@Override
public void transfer(Long oldId, Long inId, BigDecimal amount) {
accountMapper.addBalance(oldId, amount);
//int i=1/0;
accountMapper.subtractBalance(inId, amount);
}
@Override
public void delete(Long id) {
accountMapper.delete(id);
}
}
配置事务管理器
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务解析器-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
网友评论