图书类接口
package com.spring.tx; public interface BookShopDao { /** * 根据书号查找加个 * @param isbn * @return */ public int findBookPriceByIsbn(String isbn); /** * 更新书的库存 * @param isbn */ public void updateBookStock(String isbn); /** * 更新账户 * @param username * @param price */ public void updateUserAccount(String username,int price); }
图书类实现类
package com.spring.tx; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository("bookShopDao") public class BookShopDaoImpl implements BookShopDao{ @Autowired private JdbcTemplate jdbcTemplate; @Override public int findBookPriceByIsbn(String isbn) { String sql ="SELECT price FROM book WHERE isbn = ?"; return jdbcTemplate.queryForObject(sql, Integer.class,isbn); } @Override public void updateBookStock(String isbn) { // 检查库存是否足够 String sql = "SELECT stock FROM book_stock WHERE isbn = ?"; Integer queryForObject = jdbcTemplate.queryForObject(sql, Integer.class,isbn); if(queryForObject <=0){ throw new BookStockException("库存不足"); } String sql2 = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?"; jdbcTemplate.update(sql2, isbn); } @Override public void updateUserAccount(String username, int price) { // 验证余额是否够,若不足,抛出异常 String sql = "SELECT balance FROM account WHERE username = ?"; Integer balance = jdbcTemplate.queryForObject(sql,Integer.class, username); if(balance<price){ throw new UserAccountException("余额不足"); } String sql2="UPDATE account SET balance = balance - ? WHERE username = ?"; jdbcTemplate.update(sql2, price,username); } }
图书Service
package com.spring.tx; public interface BookShopService { public void purchase(String username,String isbn); }
图书Service 实现类
package com.spring.tx; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service("bookShopService") public class BookShopServiceImpl implements BookShopService { @Autowired private BookShopDao bookShopDao; // 添加事务注解 /** * propagation 事务的传播行为 ,即当前的事务方法被另一个事务方法调用时适合使用事务 * 默认值Propagation.REQUIRED 使用调用事务的方法(共用一个事务) * REQUIRES_NEW 使用自己的事务,调用事务的方法的事务被挂起 * isolation 制事务的隔离级别,常用的取值为READ_COMMITTED * rollbackFor/norollbackFor 默认情况下Spring的声明式事务对所有的运行时异常进行回滚 * readOnly 制定事务是否为只读 * timeout 制定强制回滚之前事务可以占用时间 */ @Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED,rollbackFor={UserAccountException.class} ,readOnly=true,timeout=1 ) @Override public void purchase(String username, String isbn) { // 获取单价 int price = bookShopDao.findBookPriceByIsbn(isbn); // 更新库存 bookShopDao.updateBookStock(isbn); // 更新账户 bookShopDao.updateUserAccount(username, price); } }
出账接口
package com.spring.tx; import java.util.List; public interface CashierService { public void checkout(String username,List<String> ibsns); }
出账实现类
package com.spring.tx; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service("cashierService") public class CashierServiceimpl implements CashierService { @Autowired private BookShopService bookShopService; @Transactional @Override public void checkout(String username, List<String> ibsns) { for(String ibsn:ibsns){ bookShopService.purchase(username, ibsn); } } }
异常处理类
package com.spring.tx; 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.tx; public class UserAccountException extends RuntimeException{ /** * */ private static final long serialVersionUID = 1L; public UserAccountException() { super(); // TODO Auto-generated constructor stub } public UserAccountException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public UserAccountException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public UserAccountException(String message) { super(message); // TODO Auto-generated constructor stub } public UserAccountException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
Spring配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 9 10 <!-- 配置自动扫描的包 --> 11 <context:component-scan base-package="com.spring.tx"></context:component-scan> 12 <!-- 导入资源文件 --> 13 <context:property-placeholder location="classpath:db.properties" /> 14 15 <!-- 配置C3P0数据源 --> 16 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 17 <property name="user" value="${jdbc.user}"></property> 18 <property name="password" value="${jdbc.password}"></property> 19 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> 20 <property name="driverClass" value="${jdbc.driverClass}"></property> 21 22 <property name="initialPoolSize" value="${jdbc.initPoorSize}"></property> 23 <property name="maxPoolSize" value="${jdbc.maxPoorSize}"></property> 24 </bean> 25 26 <!-- 配置Spring的JdbcTemplate --> 27 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 28 <property name="dataSource" ref="dataSource"></property> 29 </bean> 30 31 <!-- 配置事务管理器 --> 32 <bean id="transactionManager" 33 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 34 <property name="dataSource" ref="dataSource"></property> 35 </bean> 36 37 <!-- 启用事物注解 --> 38 <tx:annotation-driven transaction-manager="transactionManager"/> 39 40 </beans>
数据源
1 jdbc.user=root 2 jdbc.password=123456 3 jdbc.driverClass=com.mysql.jdbc.Driver 4 jdbc.jdbcUrl=jdbc:mysql:///spring 5 6 jdbc.initPoorSize=5 7 jdbc.maxPoorSize=10
测试类
package com.spring.junit; import java.sql.SQLException; import java.util.Arrays; import javax.sql.DataSource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import com.spring.tx.BookShopDao; import com.spring.tx.BookShopService; import com.spring.tx.CashierService; public class JdbcTest { private ApplicationContext ctx =null; private JdbcTemplate jdbcTemplate; private BookShopDao bookShopDao =null; private BookShopService bookShopService=null; private CashierService cashierService = null; { ctx =new ClassPathXmlApplicationContext("applicationContext.xml"); jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate"); bookShopDao = ctx.getBean(BookShopDao.class); bookShopService =ctx.getBean(BookShopService.class); cashierService =ctx.getBean(CashierService.class); } /** * 测试数据库连接 * @throws SQLException */ @Test public void testJdbcTest() throws SQLException { DataSource dataSource = ctx.getBean(DataSource.class); System.out.println(dataSource.getConnection()); } /** * 执行insert delete update */ @Test public void testJdbcTemplate(){ String sql = "update test1 set name = ? where id = ?"; jdbcTemplate.update(sql, "213","1"); } /** * 测试booksdao */ @Test public void testBooksShopDao(){ int findBookPriceByIsbn = bookShopDao.findBookPriceByIsbn("1001"); bookShopDao.updateBookStock("1001"); bookShopDao.updateUserAccount("1", 100); System.out.println(findBookPriceByIsbn); } /** * 测试booksService */ @Test public void testBookShopService(){ bookShopService.purchase("1", "1001"); } /** * 测试CashierService */ @Test public void testCashierService(){ cashierService.checkout("1", Arrays.asList("1002","1001")); } }
Jar包
c3p0-0.9.1.2.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
mysql-connector-java-5.1.7-bin.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar