简单搭建一个mybatis环境实现转账的模拟操作
项目列表
pom.xml依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
数据库sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_name` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`money` float NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `account` VALUES (1, \'aa\', 1000);
INSERT INTO `account` VALUES (2, \'bb\', 1000);
INSERT INTO `account` VALUES (3, \'cc\', 1000);
SET FOREIGN_KEY_CHECKS = 1;
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"> <!--加载外部properties文件-->
<!--<property name="driverClass" value="com.mysql.jdbc.Driver123"/>-->
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.qiliang.pojo"/>
</typeAliases>
<!--mybatis环境的配置-->
<environments default="test">
<environment id="test">
<!--事务管理器:由JDBC来管理-->
<transactionManager type="JDBC"/>
<!--数据源的配置:mybatis自带的连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="com.qiliang.dao.AccountDao"/>
</mappers>
</configuration>
<!--
db.properties 文件信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/数据库名?allowMultiQueries=true(执行多条SQL)
jdbc.username=root
jdbc.password=root
-->
log4j.pro
log4j.rootLogger=debug, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
工具类
public class SessionFactoryUtils {
//声明一个工厂对象
private static SqlSessionFactory factory;
//在静态代码块中创建会话工厂
static {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//得到输入流
try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
factory = builder.build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSessionFactory() {
return factory;
}
public static SqlSession getSession() {
return factory.openSession(); //自动提交事务
}
}
Config
@Configuration
@ComponentScan("com.qiliang")
public class Config { }
实体类
public class Account {
private int id;
private String accountName;
private Float money;
//省略set、get、toString
}
dao
public interface AccountDao {
@Select("select * from account")
List<Account> findAll();
@Update("update account set money=money - #{money} where account_name = #{name}")
void out(@Param("name")String outName,@Param("money")float money);
@Update("update account set money=money + #{money} where account_name = #{name}")
void in(@Param("name")String inName,@Param("money")float money);
}
service
@Service
public class AccountService {
private SqlSession session = SessionFactoryUtils.getSession();
private AccountDao mapper =
session.getMapper(AccountDao.class);
//查询测试
public List<Account> findAll() {
return mapper.findAll();
}
/**
* @param outName 支出账户
* @param inName 收入账户
* @param money 转账金额
*/
public boolean transfer(String outName, String inName, float money) {
try {
//转出
mapper.out(outName, money);
int i=1/0; //模拟异常
//转入
mapper.in(inName, money);
} catch (Exception e) {
//事务回滚
session.rollback();
System.out.println("失败原因:"+e.getMessage());
return false;
}
//提交事务
session.commit();
return true;
}
}
controller
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class AccountWeb {
@Autowired
private AccountService accountService;
@Test
public void test01(){
List<Account> list = accountService.findAll();
for (Account account : list) { System.out.println(account); }
}
/**
* outName 支出账户
* inName 收入账户
* money 转账金额
*/
@Test
public void test02(){
boolean result = accountService.transfer("aa", "bb", 100);
if(result){
System.out.println("转账成功");
} else {
System.out.println("转账失败");
}
}
}
结果不做演示,可以多次把异常 和 回滚事务的代码注释掉,看运行的区别