事务_简单转账业务模拟mybatis、Spring框架

简单搭建一个mybatis环境实现转账的模拟操作

项目列表

事务_简单转账业务模拟mybatis、Spring框架

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("转账失败");
        }
    }
}

结果不做演示,可以多次把异常 和 回滚事务的代码注释掉,看运行的区别

相关推荐