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;
package springjdbc.tx; public interface IBookShopDao { //根据isbn查找价格 public int findBookPriceByIsbn(String isbn); //根据isbn更新库存-1 public void updateBookStock(String isbn); //更新账号余额,balance - price public void updateUserAccount(String userName, String price); }
package springjdbc.tx; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository("bookShopDao") public class BookShopDaoImple implements IBookShopDao { @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 sql2 = "SELECT stock FROM book_stock WHERE isbn = ?"; int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn); if (stock == 0) { throw new BookStockException("库存不足"); } //检查书的库存,如果不够抛出异常 String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?"; jdbcTemplate.update(sql,isbn); } @Override public void updateUserAccount(String userName, String price) { String sql2 = "SELECT balance FROM account WHERE username = ?"; int balance = jdbcTemplate.queryForObject(sql2, Integer.class, userName); if (balance < Integer.valueOf(price)) { throw new UserAccountException("余额不足"); } String sql = "UPDATE account SET balance = balance - ? WHERE userName = ?"; jdbcTemplate.update(sql, price, userName); } }
package springjdbc.tx; public interface IBookShopService { public void purchase(String userName, String isbn); }
package springjdbc.tx; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service("bookShopService") public class BookShopServiceImpl implements IBookShopService { @Autowired private IBookShopDao iBookShopDao; @Override public void purchase(String userName, String isbn) { //get book price iBookShopDao.findBookPriceByIsbn(isbn); //update book stock iBookShopDao.updateBookStock(isbn); //update user account iBookShopDao.updateUserAccount(userName, isbn); } }
package springjdbc.tx; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestTx { private ApplicationContext ctx = null; private IBookShopDao iBookShopDao; private IBookShopService bookShopService; { ctx = new ClassPathXmlApplicationContext("springjdbc/application.xml"); iBookShopDao = ctx.getBean(IBookShopDao.class); bookShopService = ctx.getBean(IBookShopService.class); } @Test public void testBookShopService() { bookShopService.purchase("AA", "100"); } @Test public void testBookShopDaoFindPriceByIsbn() { System.out.println(iBookShopDao.findBookPriceByIsbn("1001")); } @Test public void testBookShopDaoUpdateBookStock() { iBookShopDao.updateBookStock("1001"); } @Test public void testBookShopDaoUserAccount() { iBookShopDao.updateUserAccount("AA","1000" ); } }
<?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" 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"> <context:component-scan base-package="springjdbc"></context:component-scan> <!-- import resource files --> <context:property-placeholder location="classpath:springjdbc/db.properties"></context:property-placeholder> <!-- C3P0 DataSource --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="initialPoolSize" value="${jdbc.initPoolSize}"/> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/> </bean> <!-- jdbc template --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 具名参数 --> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource"/> </bean> </beans>