[Spring]Spring AOP学习笔记(4)--Spring 事务
2015-09-24 17:50
489 查看
事务,具有原子性,通俗地说,就是要不都做,要不都不做。Spring作为一个框架,它也实现了原子这一点。这样,在做一些开发时,将省去很多事。以取钱为例,输出取款金额后,卡中余额减少,取款机出钞票。这3步应该是一致的,如果出现卡上余额减少,但是取款机没出钱的情况,估计银行的业务也就没人会使用了。
那么Spring是是如何实现事务的呢?以买书为例。分为三步。
Step 1: 查询价格;
Step 2:更新库存;
Step 3:更新购买者账号余额。
事务的实现,主要有2点,XML配置文件里,应该有这样的一段代码。
另外,事务上应该有这样的注释配置。
数据库设计如下:
数据库名:TransactionsTest
表名:Book,UserAccount
spring-adbc.xml
db.properties
那么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 @Override public 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://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=root password=root driverClass=com.mysql.jdbc.Driver JdbcUrl=jdbc:mysql://127.0.0.1:3307/TransactionsTest initPoolSize=5 maxPoolSize=10
package com.spring.jdbc.test2; public interface BookDao { //根据书号获取书的单价 public int findBookPriceById(int id); //更新数的库存. 使书号对应的库存 - 1 public 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 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int findBookPriceById(int id) { String sql = "select price from Book where id = ?"; Integer num = jdbcTemplate.queryForObject(sql, Integer.class, id); return num; } @Override public 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; } @Override public 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 {
@Autowired
private BookDao bookdao;
@Transactional @Override public 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"); @Test public void testfindBookPriceById() { bd.findBookPriceById(1001); System.out.println(bd); } @Test public void testUpdateBookStock() { bd.updateBookStock(1001); } @Test public void testUpdateUserAccount() { bd.updateUserAccount(2011, 60); } @Test public void testBuy() { buy1.buy(2011, 1001); } }
相关文章推荐
- JAVA中注解的简单使用
- Java中的反射机制 一个利用反射进行对象拷贝的例子
- 第一章 Java Web工作原理
- java get,post 请求
- java中的split函数用法
- jd -eclipse 放到eclipse 中进行自动反编译
- java线性查找、二分查找(2015年9月23日)
- SSH整合 简单的增删改查
- 第12章 Java内存模型与线程
- Ubuntu14.04安装JDK与配置环境变量
- 数字可以为正数或负数(可以含有小数点) java
- 得到JAVA项目根文件夹
- Java序列化与反序列化的几种方式
- eclipse下搭建SSH整合环境(Struts2+Spri 4000 ng+Hibernate+maven)
- springMVC教程中级(四)Controller中级篇1(回传、批量)
- Struts-文件上传
- JAVA CACHE
- Java SE EE ME
- Java Web - 日志-log4j(二)-- 将日志发送到邮件
- 《2016展讯校招java软开最后一道题》考点:父类子类static{}块、{}块、构造函数的调用顺序