Spring事务
ACID
原子性
一致性
隔离性
持久性
编程式/声明式
Spring事务管理抽象是PlatformTransactionManager
JDBC: DataSourceTransactionManager
JTA: JtaTransactionManager
Hibernate: HibernateTransactionManager
事务管理器以Bean形式声明在Spring IOC容器中
事务管理器
database: spring
create table book(
isbn varchar(50) primary key,
book_name varchar(50),
price int
);
create table account (
username varchar(50) primary key,
balance int,
check(balance >0 )
);
create table book_stock(
isbn varchar(50) primary key,
stock int
check(stock >0)
);
insert into book values(1001, 'java', 100);
insert into book values(1002, 'oracle', 70);
commit;
insert into account values('AA', 160);
commit;
insert into book_stock values(1001, 4);
insert into book_stock values(1002, 8);
commit;
1package springjdbc.tx; 2 3public interface IBookShopDao { 4 //根据isbn查找价格 5 public int findBookPriceByIsbn(String isbn); 6 7 //根据isbn更新库存-1 8 public void updateBookStock(String isbn); 9 10 //更新账号余额,balance - price 11 public void updateUserAccount(String userName, String price); 12} 13 14package springjdbc.tx; 15 16import org.springframework.beans.factory.annotation.Autowired; 17import org.springframework.jdbc.core.JdbcTemplate; 18import org.springframework.stereotype.Repository; 19 20@Repository("bookShopDao") 21public class BookShopDaoImple implements IBookShopDao { 22 23 @Autowired 24 private JdbcTemplate jdbcTemplate; 25 26 @Override 27 public int findBookPriceByIsbn(String isbn) { 28 String sql = "SELECT price FROM book WHERE isbn = ?"; 29 30 return jdbcTemplate.queryForObject(sql, Integer.class, isbn); 31 } 32 33 @Override 34 public void updateBookStock(String isbn) { 35 String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?"; 36 int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn); 37 if (stock == 0) { 38 throw new BookStockException("库存不足"); 39 } 40 //检查书的库存,如果不够抛出异常 41 String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?"; 42 jdbcTemplate.update(sql,isbn); 43 44 } 45 46 @Override 47 public void updateUserAccount(String userName, String price) { 48 String sql2 = "SELECT balance FROM account WHERE username = ?"; 49 int balance = jdbcTemplate.queryForObject(sql2, Integer.class, userName); 50 if (balance < Integer.valueOf(price)) { 51 throw new UserAccountException("余额不足"); 52 } 53 String sql = "UPDATE account SET balance = balance - ? WHERE userName = ?"; 54 jdbcTemplate.update(sql, price, userName); 55 } 56} 57 58package springjdbc.tx; 59 60public interface IBookShopService { 61 public void purchase(String userName, String isbn); 62 63} 64 65package springjdbc.tx; 66 67import org.springframework.beans.factory.annotation.Autowired; 68import org.springframework.stereotype.Service; 69 70@Service("bookShopService") 71public class BookShopServiceImpl implements IBookShopService { 72 @Autowired 73 private IBookShopDao iBookShopDao; 74 75 @Override 76 public void purchase(String userName, String isbn) { 77 //get book price 78 iBookShopDao.findBookPriceByIsbn(isbn); 79 80 //update book stock 81 iBookShopDao.updateBookStock(isbn); 82 83 //update user account 84 iBookShopDao.updateUserAccount(userName, isbn); 85 86 } 87} 88 89package springjdbc.tx; 90 91import org.junit.Test; 92import org.springframework.context.ApplicationContext; 93import org.springframework.context.support.ClassPathXmlApplicationContext; 94 95public class TestTx { 96 private ApplicationContext ctx = null; 97 98 private IBookShopDao iBookShopDao; 99 private IBookShopService bookShopService; 100 { 101 ctx = new ClassPathXmlApplicationContext("springjdbc/application.xml"); 102 iBookShopDao = ctx.getBean(IBookShopDao.class); 103 bookShopService = ctx.getBean(IBookShopService.class); 104 } 105 106 @Test 107 public void testBookShopService() { 108 bookShopService.purchase("AA", "100"); 109 } 110 111 @Test 112 public void testBookShopDaoFindPriceByIsbn() { 113 System.out.println(iBookShopDao.findBookPriceByIsbn("1001")); 114 } 115 116 @Test 117 public void testBookShopDaoUpdateBookStock() { 118 119 iBookShopDao.updateBookStock("1001"); 120 } 121 122 @Test 123 public void testBookShopDaoUserAccount() { 124 iBookShopDao.updateUserAccount("AA","1000" ); 125 } 126} 127 128<?xml version="1.0" encoding="UTF-8"?> 129<beans xmlns="http://www.springframework.org/schema/beans" 130 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 131 xmlns:context="http://www.springframework.org/schema/context" 132 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.xsd"> 133 134 <context:component-scan base-package="springjdbc"></context:component-scan> 135 <!-- import resource files --> 136 <context:property-placeholder location="classpath:springjdbc/db.properties"></context:property-placeholder> 137 138 <!-- C3P0 DataSource --> 139 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 140 <property name="user" value="${jdbc.user}"/> 141 <property name="password" value="${jdbc.password}"/> 142 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> 143 <property name="driverClass" value="${jdbc.driverClass}"/> 144 <property name="initialPoolSize" value="${jdbc.initPoolSize}"/> 145 <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/> 146 </bean> 147 148 <!-- jdbc template --> 149 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 150 <property name="dataSource" ref="dataSource"/> 151 </bean> 152 153 <!-- 具名参数 --> 154 <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> 155 <constructor-arg ref="dataSource"/> 156 </bean> 157</beans>