[Spring]Spring AOP学习笔记(4)--Spring 事务

来源:互联网 发布:卡宾雪板 知乎 编辑:程序博客网 时间:2024/04/29 22:09

事务,具有原子性,通俗地说,就是要不都做,要不都不做。Spring作为一个框架,它也实现了原子这一点。这样,在做一些开发时,将省去很多事。以取钱为例,输出取款金额后,卡中余额减少,取款机出钞票。这3步应该是一致的,如果出现卡上余额减少,但是取款机没出钱的情况,估计银行的业务也就没人会使用了。

那么Spring是是如何实现事务的呢?以买书为例。分为三步。

Step 1: 查询价格;

Step 2:更新库存;

Step 3:更新购买者账号余额。


事务的实现,主要有2点,XML配置文件里,应该有这样的一段代码。

<!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 启用事务注解 --><tx:annotation-driven transaction-manager="transactionManager"/>

另外,事务上应该有这样的注释配置。

@Transactional@Overridepublic void buy(int UserId, int id){System.out.println(bookdao);//1.查询价格int price = bookdao.findBookPriceById(id);//2.更新库存bookdao.updateBookStock(id);//3.更新用户余额bookdao.updateUserAccount(UserId, price);}

数据库设计如下:

数据库名:TransactionsTest

表名:Book,UserAccount



spring-adbc.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><!-- 自动扫描包 --><context:component-scan base-package="com.spring.jdbc.test2"></context:component-scan><!-- 导入资源文件 --><context:property-placeholder location="classpath:db.properties" /><!-- 配置c3p0数据源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="${username}"></property><property name="password" value="${password}"></property><property name="jdbcUrl" value="${JdbcUrl}"></property><property name="driverClass" value="${driverClass}"></property><property name="numHelperThreads" value="10"></property><property name="initialPoolSize" value="${initPoolSize}"></property><property name="maxPoolSize" value="${maxPoolSize}"></property></bean><!-- 配置JDBCTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 启用事务注解 --><tx:annotation-driven transaction-manager="transactionManager"/></beans>

db.properties

username=rootpassword=rootdriverClass=com.mysql.jdbc.DriverJdbcUrl=jdbc:mysql://127.0.0.1:3307/TransactionsTestinitPoolSize=5maxPoolSize=10

package com.spring.jdbc.test2;public interface BookDao {//根据书号获取书的单价public int findBookPriceById(int id);//更新数的库存. 使书号对应的库存 - 1public void updateBookStock(int id);//更新用户的账户余额public void updateUserAccount(int UserId, int price);}

package com.spring.jdbc.test2;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;@Repository("bookDao")public class BookDaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic int findBookPriceById(int id) {String sql = "select price from Book where id = ?";Integer num = jdbcTemplate.queryForObject(sql, Integer.class, id);return num;}@Overridepublic void updateBookStock(int id) {String sql="select bookstock from Book where id=?";Integer bookstock = jdbcTemplate.queryForObject(sql, Integer.class, id);if(bookstock<1){throw new BookStockException("库存不足");}sql = "update Book set bookstock=bookstock-1 where id=?";jdbcTemplate.update(sql, id);return;}@Overridepublic void updateUserAccount(int UserId, int price) {String sql="select Account from UserAccount where UserId=?";Integer account = jdbcTemplate.queryForObject(sql, Integer.class, UserId);if(account<price){throw new AccountException("余额不足");}sql = "update UserAccount set Account=Account-? where UserId=?";jdbcTemplate.update(sql, price, UserId);return;}}

package com.spring.jdbc.test2;public interface Buy {public void  buy(int UserId, int id);}

package com.spring.jdbc.test2;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Service("buyimpl")public class BuyImpl implements Buy {@Autowiredprivate BookDao bookdao;@Transactional@Overridepublic void buy(int UserId, int id){System.out.println(bookdao);//1.查询价格int price = bookdao.findBookPriceById(id);//2.更新库存bookdao.updateBookStock(id);//3.更新用户余额bookdao.updateUserAccount(UserId, price);}}

package com.spring.jdbc.test2;public class BookStockException extends RuntimeException{/** *  */private static final long serialVersionUID = 1L;public BookStockException() {super();// TODO Auto-generated constructor stub}public BookStockException(String message, Throwable cause,boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);// TODO Auto-generated constructor stub}public BookStockException(String message, Throwable cause) {super(message, cause);// TODO Auto-generated constructor stub}public BookStockException(String message) {super(message);// TODO Auto-generated constructor stub}public BookStockException(Throwable cause) {super(cause);// TODO Auto-generated constructor stub}}

package com.spring.jdbc.test2;public class AccountException extends RuntimeException{/** *  */private static final long serialVersionUID = 1L;public AccountException() {super();// TODO Auto-generated constructor stub}public AccountException(String message, Throwable cause,boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);// TODO Auto-generated constructor stub}public AccountException(String message, Throwable cause) {super(message, cause);// TODO Auto-generated constructor stub}public AccountException(String message) {super(message);// TODO Auto-generated constructor stub}public AccountException(Throwable cause) {super(cause);// TODO Auto-generated constructor stub}}


package com.spring.jdbc.test2;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;public class TestOne {private ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-jdbc.xml");BookDao bd = ctx.getBean(BookDaoImpl.class);Buy buy1 = (Buy) ctx.getBean("buyimpl");@Testpublic void testfindBookPriceById() {bd.findBookPriceById(1001);System.out.println(bd);}@Testpublic void testUpdateBookStock() {bd.updateBookStock(1001);}@Testpublic void testUpdateUserAccount() {bd.updateUserAccount(2011, 60);}@Testpublic void testBuy() {buy1.buy(2011, 1001);}}


0 0