JavaSE

Spring事务管理---转账案例搭建

2018-04-20  本文已影响1人  熊猫读书营

上一篇文章总结了Spring事务管理的相关知识点。接下来写一个模拟银行转账的案例来实际操作一下。

一、转账环境搭建

  1. 创建数据库表
    CREATE DATABASE spring_transation;
    USE spring_transation;
    CREATE TABLE account (
        id int(11) NOT NULL AUTO_INCREMENT,
        name varchar(20) NOT NULL,
        money double DEFAULT NULL,
        PRIMARY KEY (id)
    )
  1. 插入初始数据
    INSERT INTO account VALUES ('1','aaa',1000);
    INSERT INTO account VALUES ('2','bbb',1000);
    INSERT INTO account VALUES ('3','ccc',1000);
  1. 创建Spring项目
    使用IDEA,用Maven来构建一个Spring项目。
    参考链接:IDEA搭建Spring项目(Maven版)

pom.xml文件中引入所需要的依赖:

<dependencies>
    <!--spring所需依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.3.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.8.RELEASE</version>
    </dependency>
    <!--其他需要的包-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.4</version>
    </dependency>
    <!--mysql driver-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
    <!--jdbc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>3.0.5.RELEASE</version>
    </dependency>
    <!--c3p0-->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

我的项目目录结构如下:

  1. 定义接口方法
    ①新建业务层接口AccountService,定义转账方法
//转账业务接口
public interface AccountService {
    public void transfer(String out, String in, Double money);
}

②业务层接口实现类

public class AccountServiceImpl implements AccountService{
  
    @Override
    public void transfer(String out, String in, Double money) {

    }
}

③新建数据访问层接口AccountDao

//转账Dao层接口
public interface AccountDao {

    public void outMoney(String out, Double money);
    public void inMoney(String in, Double money);

}

④Dao接口实现类
Spring中提供了一个关于jdbc操作的模板类,只需让Dao实现类继承JdbcDaoSupport即可。

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    @Override
    public void outMoney(String out, Double money) {
        
    }

    @Override
    public void inMoney(String in, Double money) {
        
    }
}
  1. 加载Bean配置
    修改applicationContext.xml文件:
    ①引入数据库属性文件
    <context:property-placeholder location="classpath:jdbc.properties"/>

②配置c3po连接池

<!-- 配置C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver_class}"/>
        <property name="jdbcUrl" value="${jdbc.connection.url}"/>
        <property name="user" value="${jdbc.connection.username}"/>
        <property name="password" value="${jdbc.connection.password}"/>
    </bean>

③配置Dao层类

<!--配置Dao的类-->
    <bean id="accountDao" class="cn.lovebugs.spring.demo.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/><!--注入连接池,因为DaoImpl类中继承了jdbc模板类,所以这里只要注入连接池就可以获得jdbc模板-->
    </bean>

④配置业务层类

<!--配置业务层类-->
    <bean id="accountService" class="cn.lovebugs.spring.demo.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>
  1. 完善接口方法
    前面已经定义好了转账所需要的方法,也做好了先相关的配置及jdbc模板,接下来只需完善转账方法即可。
    ①完善业务层接口实现类
public class AccountServiceImpl implements AccountService{

    //注入转账的Dao类,xml文件中的<property name="accountDao" ref="accountDao"/>
    private AccountDao accountDao;

    //设值注入
    public void setAccountDao(AccountDao accountDao){
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out,money);
        accountDao.inMoney(in,money);
    }
}

②完善Dao层实现类

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    @Override
    public void outMoney(String out, Double money) {
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql,money,out);//jdbc模板类执行sql语句
    }

    @Override
    public void inMoney(String in, Double money) {
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql,money,in);
    }
}

二、测试

上面已经搭建好了基本的转账环境,接下来进行测试。
这里额外引入了一个测试相关的jar包:spring-test-3.2.0.RELEASE.jar

  1. 新建测试类,方法如下:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class SpringTest {

    @Resource(name = "accountService")
    private AccountService accountService;//引入业务类

    @Test
    public void test(){
        accountService.transfer("aaa","bbb",200d);
    }

}
  1. 运行test()方法,查看数据库结果

转账成功。

三、无事务管理造成的问题

前面所搭建的转账案例是没有进行事务管理的情况下实现的,因此它存在很大地安全隐患。比如a要向b转账200元,当a的账户减少200元后,此时如果程序发生异常被终止,那么b的账户就无法增加200元,这样就造成了数据不一致的问题。

如下示例:
在AccountServiceImpl类的transfer()方法中加入一条异常语句

@Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out,money);
        int a = 1 / 0; //强制使程序发生异常
        accountDao.inMoney(in,money);
    }

此时再运行test()方法后查看数据库结果

结果显然发现a的账户减少了200元,但是b的账户并没有改变。
这就看出了不加事务管理所造成的后果。

下一篇文章将会写一下如何进行事务处理。



微信公众号【IT资源社】
本公众号致力于免费分享全网最优秀的视频资源,学习资料,面试经验等,前端,PHP,JAVA,算法,Python,大数据等等,你想要的这都有,还会分享优质博文,提高你的认知与思维

IT资源社-QQ交流群:625494093
要进微信交流群的话加微信:super1319164238
微信搜索公众号:IT资源社 或者扫描下方二维码直接关注,


原创文章,转载请注明出处
上一篇下一篇

猜你喜欢

热点阅读