(VI)事务:Spring 事务案例

一、测试数据准备

  1、需求

    

  2、数据表

CREATE TABLE book (
  isbn VARCHAR (50) PRIMARY KEY,
  book_name VARCHAR (100),
  price INT
) ;

CREATE TABLE book_stock (
  isbn VARCHAR (50) PRIMARY KEY,
  stock INT,
  CHECK (stock > 0)
) ;

CREATE TABLE account (
  username VARCHAR (50) PRIMARY KEY,
  balance INT,
  CHECK (balance > 0)
) ;

INSERT INTO account (`username`,`balance`) VALUES ('Tom',100000);
INSERT INTO account (`username`,`balance`) VALUES ('Jerry',150000);

INSERT INTO book (`isbn`,`book_name`,`price`) VALUES ('ISBN-001','book01',100);
INSERT INTO book (`isbn`,`book_name`,`price`) VALUES ('ISBN-002','book02',200);
INSERT INTO book (`isbn`,`book_name`,`price`) VALUES ('ISBN-003','book03',300);
INSERT INTO book (`isbn`,`book_name`,`price`) VALUES ('ISBN-004','book04',400);
INSERT INTO book (`isbn`,`book_name`,`price`) VALUES ('ISBN-005','book05',500);

INSERT INTO book_stock (`isbn`,`stock`) VALUES ('ISBN-001',1000);
INSERT INTO book_stock (`isbn`,`stock`) VALUES ('ISBN-002',2000);
INSERT INTO book_stock (`isbn`,`stock`) VALUES ('ISBN-003',3000);
INSERT INTO book_stock (`isbn`,`stock`) VALUES ('ISBN-004',4000);
INSERT INTO book_stock (`isbn`,`stock`) VALUES ('ISBN-005',5000);

二、环境搭建

  在配置文件中配置数据源和 JdbcTemplate:

    <context:component-scan base-package="com.njf.tx"></context:component-scan>

    <context:property-placeholder location="db.properties"></context:property-placeholder>

    <!--  配置数据源  -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

三、业务代码

  BookDao:

@Repository
public class BookDao {


    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 1、减余额
     *
     * 减去用户的余额
     */
    public void updateBalance(String userName, int price) {
        String sql = "UPDATE account SET balance = balance - ? WHERE username = ?";
        int i = jdbcTemplate.update(sql,price, userName);
    }

    /**
     * 2. 获取某本图书的价格
     * @return
     */
    public int getPrice(String isbn) {
        String sql = "SELECT price FROM book WHERE isbn = ?";
        return jdbcTemplate.queryForObject(sql, Integer.class, isbn);
    }

    /**
     * 3. 减去对应图书的库存,每次减1
     */
    public void updateStock(String isbn) {
        String sql = "UPDATE book_stock SET stock = stock - 1 WHERE isbn = ?";
        jdbcTemplate.update(sql,isbn);
    }
}

  BookService:

@Service
public class BookService {

    @Autowired
    private BookDao bookDao;

    /**
     * 结账,哪个用户买了哪本书
     * @param userName
     * @param isbn
     */
    public void checkOut(String userName, String isbn) {
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        bookDao.updateBalance(userName, price);
    }
}

  测试:

public class TxTest {

    ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");

    @Test
    public void test() {
        BookService bookService = ioc.getBean(BookService.class);

        bookService.checkOut("Tom", "ISBN-001");

        System.out.println("结账完成");
    }
}

四、添加事务管理

  1、配置事务管理器

    <!--1: 配置事务管理器让其进行事务控制-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--控制住数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

  2、开启基于注解的事务控制

    <!-- 2: 开启基于注解的事务控制模式:依赖 tx 名称空间  -->
    <tx:annotation-driven transaction-manager="transactionManager" />

  3、给事务方法加注解

    @Transactional
    public void checkOut(String userName, String isbn) {
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        int i = 10 / 0;

        bookDao.updateBalance(userName, price);

    }

  测试:当给加了@Transactional 方法的内部手动制造异常情况,整个操作都会回滚,满足事务的要求。

原文地址:https://www.cnblogs.com/niujifei/p/15489658.html