spring boot学习(6) SpringBoot 之事务管理

两个操作要么同时成功,要么同时失败;
事务的一致性;
以前学ssh ssm都有事务管理service层通过applicationContext.xml配置,所有service方法都加上事务操作;

用来保证一致性,即service方法里的多个dao操作,要么同时成功,要么同时失败;

 

下面模拟用户转账,a用户转账给b用户200元;需要事务管理;
项目结构:
 
1.代码:                    
com.cy.entity.Account.java;
package com.cy.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * 账户实体
 * @author CY
 *
 */
@Entity
@Table(name="t_account")
public class Account {
    
    @Id
    @GeneratedValue
    private Integer id;
    
    @Column(length=50)
    private String userName;
    
    private float balance;    //余额

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public float getBalance() {
        return balance;
    }

    public void setBalance(float balance) {
        this.balance = balance;
    }
    
    
    
}

账户dao接口:com.cy.dao.AccountDao.java:

package com.cy.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import com.cy.entity.Account;

/**
 * 账户Dao接口
 * JpaRepository<T, ID>第二个参数是主键类型
 * @author CY
 *
 */
public interface AccountDao extends JpaRepository<Account, Integer>{

}

账户service接口:com.cy.service.AccountService.java:

package com.cy.service;

/**
 * 账户Service接口
 * @author CY
 *
 */
public interface AccountService {
    
    /**
     * 从fromUser转账到toUser,account钱;
     * @param fromUser
     * @param toUser
     * @param account
     */
    public void transferAccounts(int fromUser, int toUser, float account);
}

账户接口实现类:com.cy.service.impl.AccountServiceImpl.java;

package com.cy.service.impl;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import org.springframework.stereotype.Service;
import com.cy.dao.AccountDao;
import com.cy.entity.Account;
import com.cy.service.AccountService;

/**
 * 账户service实现类
 * @author CY
 *
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService{
    
    @Resource
    private AccountDao accountDao;
    
    /**
     * 从A用户转账到B用户account元;
     * 也就是两个操作:
     * A用户减去accout元,B用户加上account元
     */
    @Override
    @Transactional
    public void transferAccounts(int fromUser, int toUser, float account) {
        Account a = accountDao.getOne(fromUser);
        a.setBalance(a.getBalance() - account);
        accountDao.save(a);
        
        Account b = accountDao.getOne(toUser);
        b.setBalance(b.getBalance() + account);
        int i = 1/0;        //这里制造个异常
        accountDao.save(b);
    }
    
}

com.cy.controller.AccountController.java来模拟用户转账:

这里返回json数据格式,成功ok,失败no

package com.cy.controller;

import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cy.service.AccountService;

/**
 * 账户Controller层
 * @author CY
 *
 */
@RestController
@RequestMapping("/account")
public class AccountController {
    
    @Resource
    private AccountService accountService;
    
    @RequestMapping("/transfer")
    public String transferAccount(){
        try{
            accountService.transferAccounts(1, 2, 200);
            return "ok";
        }catch(Exception e){
            return "no";
        }
    }
}

 

2.测试:

启动项目,查看新建的表t_account:

mysql> desc t_account;
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| balance   | float       | NO   |     | NULL    |                |
| user_name | varchar(50) | YES  |     | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

弄点数据:

mysql> select * from t_account;
+----+---------+-----------+
| id | balance | user_name |
+----+---------+-----------+
|  1 |     700 | zhangsan  |
|  2 |     300 | lisi      |
+----+---------+-----------+

浏览器http://localhost/account/transfer:

1)显示no,说明转账失败;

2)数据库数据,zhangsan仍然是700,lisi仍然是300,保证了数据一致性;

查看发出的sql:

Hibernate: select account0_.id as id1_0_0_, account0_.balance as balance2_0_0_, account0_.user_name as user_nam3_0_0_ from t_account account0_ where account0_.id=?
Hibernate: select account0_.id as id1_0_0_, account0_.balance as balance2_0_0_, account0_.user_name as user_nam3_0_0_ from t_account account0_ where account0_.id=?
没有执行保存,全部弄完了才保存;

 

说明:

这里使用的是:import javax.transaction.Transactional;(这个是jpa规范)
使用import org.springframework.transaction.annotation.Transactional也行;(这个spring实现了jpa规范)

 

posted on 2018-03-25 14:46  有点懒惰的大青年  阅读(1004)  评论(0编辑  收藏  举报