BookDao.java:
package com.atguigu.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class BookDao { @Autowired JdbcTemplate jdbcTemplate; /** * 1、减余额 * * 减去某个用户的余额 */ public void updateBalance(String userName,int price){ String sql = "UPDATE account SET balance=balance-? WHERE username=?"; jdbcTemplate.update(sql, price,userName); } /** * 2、按照图书的ISBN获取某本图书的价格 * @return */ public int getPrice(String isbn){ String sql = "SELECT price FROM book WHERE isbn=?"; return jdbcTemplate.queryForObject(sql, Integer.class, isbn); } /** * 3、减库存;减去某本书的库存;为了简单期间每次减一 */ public void updateStock(String isbn){ String sql = "UPDATE book_stock SET stock=stock-1 WHERE isbn=?"; jdbcTemplate.update(sql, isbn); } /** * 4、改图书价格 * @param isbn * @param price */ public void updatePrice(String isbn,int price){ String sql = "update book set price=? where isbn=?"; jdbcTemplate.update(sql, price,isbn); } }
BookService.java:
package com.atguigu.service; import java.io.FileInputStream; import java.io.FileNotFoundException; 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; import com.atguigu.dao.BookDao; @Service public class BookService { @Autowired BookDao bookDao; public void checkout(String username,String isbn){ bookDao.updateStock(isbn); int price = bookDao.getPrice(isbn); bookDao.updateBalance(username, price); int i = 10/0; } public void updatePrice(String isbn,int price){ bookDao.updatePrice(isbn, price); } public int getPrice(String isbn){ return bookDao.getPrice(isbn); } public void mulTx(){ checkout("Tom", "ISBN-001"); updatePrice("ISBN-002", 998); //int i=10/0; } }
MulService.java:
package com.atguigu.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class MulService { private BookService bookService; public void mulTx(){ bookService.checkout("Tom", "ISBN-001"); bookService.updatePrice("ISBN-002", 998); } }
TxTest.java:
1 package com.atguigu.test; 2 import java.io.FileNotFoundException; 3 4 import org.junit.Test; 5 import org.springframework.context.ApplicationContext; 6 import org.springframework.context.support.ClassPathXmlApplicationContext; 7 8 import com.atguigu.service.BookService; 9 import com.atguigu.service.MulService; 10 11 public class TxTest { 12 13 ApplicationContext ioc = new ClassPathXmlApplicationContext("tx.xml"); 14 15 /** 16 * 有事务的业务逻辑,容器中保存的是这个业务逻辑的代理对象 17 * @throws FileNotFoundException 18 * 19 * 20 * multx(){ 21 * //REQUIRED 22 * A(){ 23 * //REQUIRES_NEW 24 * B(){} 25 * //REQUIRED 26 * c(){} 27 * } 28 * 29 * //REQUIRES_NEW 30 * D(){ 31 * DDDD()// REQUIRES_NEW不崩,REQUIRED崩 32 * //REQUIRED 33 * E(){ 34 * //REQUIRES_NEW 35 * F(){ 36 * //10/0(E崩,G崩,D崩,A,C崩) 37 * } 38 * } 39 * //REQUIRES_NEW 40 * G(){} 41 * } 42 * 43 * 44 * 10/0(B成功,D整个分支下全部成功) 45 * 任何处崩,已经执行的REQUIRES_NEW都会成功; 46 * 47 * 如果是REQUIRED;事务的属性都是继承于大事务的; 48 * 而propagation=Propagation.REQUIRES_NEW可以调整 49 * 默认:REQUIRED; 50 * 51 * REQUIRED:将之前事务用的connection传递给这个方法使用; 52 * REQUIRES_NEW:这个方法直接使用新的connection; 53 * } 54 * 55 */ 56 @Test 57 public void test() throws FileNotFoundException { 58 BookService bookService = ioc.getBean(BookService.class); 59 bookService.checkout("Tom", "ISBN-001"); 60 //MulService bean = ioc.getBean(MulService.class); 61 //bean.mulTx(); 62 63 //bookService.checkout("Tom", "ISBN-001"); 64 //int price = bookService.getPrice("ISBN-001"); 65 //System.out.println("读取到的数据:"+price); 66 //System.out.println(bookService.getClass()); 67 68 //效果都没改(相当于回滚了),虽然mulTx的两个方法都开新车 69 //bookService.mulTx(); 70 71 System.out.println(bookService.getClass()); 72 //如果是MulService --mulTx()---调用bookService两个方法 73 //BookService---mulTx()--直接调用两个方法 74 75 /*** 76 * MulServiceProxy.mulTx(){ 77 * bookServiceProxy.checkout(); 78 * bookServiceProxy.updatePrice(); 79 * } 80 * 81 * 82 * 本类方法的嵌套调用就只是一个事务; 83 * BookServiceProxy.mulTx(){ 84 * checkout(); 85 * updatePrice(); 86 * //相当于 87 * bookDao.updateStock(isbn); 88 * int price = bookDao.getPrice(isbn); 89 * bookDao.updateBalance(username, price); 90 * 91 * bookDao.updatePrice(isbn, price); 92 * } 93 */ 94 95 } 96 97 }
tx.xml:
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 xmlns:aop="http://www.springframework.org/schema/aop" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 9 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 10 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 11 12 <context:component-scan base-package="com.atguigu"></context:component-scan> 13 14 15 <!-- 0、引入外部配置文件 --> 16 <context:property-placeholder location="classpath:dbconfig.properties" /> 17 <!-- 1、配置数据源 --> 18 <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 19 <property name="user" value="${jdbc.user}"></property> 20 <property name="password" value="${jdbc.password}"></property> 21 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> 22 <property name="driverClass" value="${jdbc.driverClass}"></property> 23 </bean> 24 <!-- 2、配置JdbcTemplate操作数据库 value="#{pooledDataSource}" ref="pooledDataSource"--> 25 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 26 <property name="dataSource" value="#{pooledDataSource}"></property> 27 </bean> 28 29 <!-- 3、配置声明式事务 30 1)、Spring中提供事务管理器(事务切面),配置这个事务管理器 31 2)、开启基于注解的事务式事务;依赖tx名称空间 32 3)、给事务方法加注解 33 --> 34 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 35 <property name="dataSource" ref="pooledDataSource"></property> 36 </bean> 37 38 <!-- 39 基于xml配置的事务;依赖tx名称空间和aop名称空间 40 1)、Spring中提供事务管理器(事务切面),配置这个事务管理器 41 2)、配置出事务方法; 42 3)、告诉Spring哪些方法是事务方法; 43 (事务切面按照我们的切入点表达式去切入事务方法) 44 --> 45 <aop:config> 46 <aop:pointcut expression="execution(* com.atguigu.ser*.*.*(..))" id="txPoint"/> 47 <!-- 事务建议;事务增强 advice-ref:指向事务管理器的配置 --> 48 <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"/> 49 </aop:config> 50 51 <!-- 配置事务管理器; 事务建议;事务增强;事务属性; 52 transaction-manager="transactionManager":指定是配置哪个事务管理器; 53 --> 54 <tx:advice id="myAdvice" transaction-manager="transactionManager"> 55 <!--事务属性 --> 56 <tx:attributes> 57 <!-- 指明哪些方法是事务方法; 58 切入点表达式只是说,事务管理器要切入这些方法, 59 哪些方法加事务使用tx:method指定的 --> 60 <tx:method name="*"/> 61 <tx:method name="checkout" propagation="REQUIRED" timeout="-1"/> 62 <tx:method name="get*" read-only="true"/> 63 </tx:attributes> 64 </tx:advice> 65 66 <!-- 都用;重要的用配置,不重要的用注解 --> 67 68 </beans>