本文实例为大家分享了Spring使用注解和配置文件配置事务的具体代码,供大家参考,具体内容如下
需求图:
使用注解配置事务:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.atguigu.spring.tx;
public interface BookShopDao {
//根据书号获取书的单价 public int findBookPriceByIsbn(String isbn);
//更新数的库存. 使书号对应的库存 - 1 public void updateBookStock(String isbn);
//更新用户的账户余额: 使 username 的 balance - price public void updateUserAccount(String username, int price); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package com.atguigu.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 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, int price) { //验证余额是否足够, 若不足, 则抛出异常 String sql2 = "SELECT balance FROM account WHERE username = ?" ; int balance = jdbcTemplate.queryForObject(sql2, Integer. class , username); if (balance < price){ throw new UserAccountException( "余额不足!" ); }
String sql = "UPDATE account SET balance = balance - ? WHERE username = ?" ; jdbcTemplate.update(sql, price, username); }
} |
1 2 3 4 5 6 7 |
package com.atguigu.spring.tx;
public interface BookShopService {
public void purchase(String username, String isbn);
} |
事务配置的核心部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package com.atguigu.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;
//添加事务注解 //1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时 //REQUIRED:为默认取值, 被调用的事务一个执行失败整个大事务就回滚 //REQUIRES_NEW:调用的事务如果执行成功就保存结果不会被回滚,其他事务执行失败不会影响到它 //2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED //3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的 //属性进行设置. 通常情况下取默认值即可. //4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据, //这样可以帮助数据库引擎优化事务. 若方法只读取数据库值, 应设置 readOnly=true //5.使用 timeout 指定事务最多可以占用的时间,若超过时间则强制回滚 // @Transactional(propagation=Propagation.REQUIRES_NEW, // isolation=Isolation.READ_COMMITTED, // noRollbackFor={UserAccountException.class}) @Transactional (propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED, readOnly= false , timeout= 3 ) @Override public void purchase(String username, String isbn) {
try { Thread.sleep( 5000 ); } catch (InterruptedException e) {}
//1. 获取书的单价 int price = bookShopDao.findBookPriceByIsbn(isbn);
//2. 更新数的库存 bookShopDao.updateBookStock(isbn);
//3. 更新用户余额 bookShopDao.updateUserAccount(username, price); }
} |
1 2 3 4 5 6 7 8 9 |
package com.atguigu.spring.tx;
import java.util.List;
public interface Cashier {
public void checkout(String username, List<String> isbns);
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.atguigu.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 ( "cashier" ) public class CashierImpl implements Cashier {
@Autowired private BookShopService bookShopService;
@Transactional @Override public void checkout(String username, List<String> isbns) { for (String isbn: isbns){ bookShopService.purchase(username, isbn); } }
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
package com.atguigu.spring.tx;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTransactionTest {
private ApplicationContext ctx = null ; private BookShopDao bookShopDao = null ; private BookShopService bookShopService = null ; private Cashier cashier = null ;
{ ctx = new ClassPathXmlApplicationContext( "applicationContext.xml" ); bookShopDao = ctx.getBean(BookShopDao. class ); bookShopService = ctx.getBean(BookShopService. class ); cashier = ctx.getBean(Cashier. class ); }
@Test public void testTransactionlPropagation(){ cashier.checkout( "AA" , Arrays.asList( "1001" , "1002" )); }
@Test public void testBookShopService(){ bookShopService.purchase( "AA" , "1001" ); }
@Test public void testBookShopDaoUpdateUserAccount(){ bookShopDao.updateUserAccount( "AA" , 200 ); }
@Test public void testBookShopDaoUpdateBookStock(){ bookShopDao.updateBookStock( "1001" ); }
@Test public void testBookShopDaoFindPriceByIsbn() { System.out.println(bookShopDao.findBookPriceByIsbn( "1001" )); }
} |
BookStockException、UserAccountException为自定义异常类!
配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://HdhCmsTestspringframework.org/schema/beans" xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance" xmlns:context = "http://HdhCmsTestspringframework.org/schema/context" xmlns:tx = "http://HdhCmsTestspringframework.org/schema/tx" xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/beans http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd http://HdhCmsTestspringframework.org/schema/tx http://HdhCmsTestspringframework.org/schema/tx/spring-tx-4.0.xsd http://HdhCmsTestspringframework.org/schema/context http://HdhCmsTestspringframework.org/schema/context/spring-context-4.0.xsd">
< context:component-scan base-package = "com.atguigu.spring" ></ context:component-scan >
<!-- 导入资源文件 --> < context:property-placeholder location = "classpath:db.properties" />
<!-- 配置 C3P0 数据源 --> < bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" > < property name = "user" value = "${jdbc.user}" ></ property > < property name = "password" value = "${jdbc.password}" ></ property > < property name = "jdbcUrl" value = "${jdbc.jdbcUrl}" ></ property > < property name = "driverClass" value = "${jdbc.driverClass}" ></ property >
< property name = "initialPoolSize" value = "${jdbc.initPoolSize}" ></ property > < property name = "maxPoolSize" value = "${jdbc.maxPoolSize}" ></ property > </ bean >
<!-- 配置 Spirng 的 JdbcTemplate --> < bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate" > < property name = "dataSource" ref = "dataSource" ></ property > </ bean >
<!-- 配置 NamedParameterJdbcTemplate, 该对象可以使用具名参数, 其没有无参数的构造器, 所以必须为其构造器指定参数 --> < bean id = "namedParameterJdbcTemplate" class = "org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate" > < constructor-arg ref = "dataSource" ></ constructor-arg > </ bean >
<!-- 配置事务管理器 --> < bean id = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > < property name = "dataSource" ref = "dataSource" ></ property > </ bean >
<!-- 启用事务注解 --> < tx:annotation-driven transaction-manager = "transactionManager" />
</ beans > |
配置文件(使用配置文件配置事务,以上类的注解需要全部删除):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://HdhCmsTestspringframework.org/schema/beans" xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance" xmlns:context = "http://HdhCmsTestspringframework.org/schema/context" xmlns:tx = "http://HdhCmsTestspringframework.org/schema/tx" xmlns:aop = "http://HdhCmsTestspringframework.org/schema/aop" xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/aop http://HdhCmsTestspringframework.org/schema/aop/spring-aop-4.0.xsd http://HdhCmsTestspringframework.org/schema/beans http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd http://HdhCmsTestspringframework.org/schema/tx http://HdhCmsTestspringframework.org/schema/tx/spring-tx-4.0.xsd http://HdhCmsTestspringframework.org/schema/context http://HdhCmsTestspringframework.org/schema/context/spring-context-4.0.xsd">
< context:component-scan base-package = "com.atguigu.spring" ></ context:component-scan >
<!-- 导入资源文件 --> < context:property-placeholder location = "classpath:db.properties" />
<!-- 配置 C3P0 数据源 --> < bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" > < property name = "user" value = "${jdbc.user}" ></ property > < property name = "password" value = "${jdbc.password}" ></ property > < property name = "jdbcUrl" value = "${jdbc.jdbcUrl}" ></ property > < property name = "driverClass" value = "${jdbc.driverClass}" ></ property >
< property name = "initialPoolSize" value = "${jdbc.initPoolSize}" ></ property > < property name = "maxPoolSize" value = "${jdbc.maxPoolSize}" ></ property > </ bean >
<!-- 配置 Spirng 的 JdbcTemplate --> < bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate" > < property name = "dataSource" ref = "dataSource" ></ property > </ bean >
<!-- 配置 bean --> < bean id = "bookShopDao" class = "com.atguigu.spring.tx.xml.BookShopDaoImpl" > < property name = "jdbcTemplate" ref = "jdbcTemplate" ></ property > </ bean >
< bean id = "bookShopService" class = "com.atguigu.spring.tx.xml.service.impl.BookShopServiceImpl" > < property name = "bookShopDao" ref = "bookShopDao" ></ property > </ bean >
< bean id = "cashier" class = "com.atguigu.spring.tx.xml.service.impl.CashierImpl" > < property name = "bookShopService" ref = "bookShopService" ></ property > </ bean >
<!-- 1. 配置事务管理器 --> < bean id = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > < property name = "dataSource" ref = "dataSource" ></ property > </ bean >
<!-- 2. 配置事务属性 --> < tx:advice id = "txAdvice" transaction-manager = "transactionManager" > < tx:attributes > <!-- 根据方法名指定事务的属性 --> < tx:method name = "purchase" propagation = "REQUIRES_NEW" /> < tx:method name = "get*" read-only = "true" /> < tx:method name = "find*" read-only = "true" /> < tx:method name = "*" /> </ tx:attributes > </ tx:advice >
<!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 --> < aop:config > < aop:pointcut expression = "execution(* com.atguigu.spring.tx.xml.service.*.*(..))" id = "txPointCut" /> < aop:advisor advice-ref = "txAdvice" pointcut-ref = "txPointCut" /> </ aop:config >
</ beans > |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
原文链接:https://blog.csdn.net/x297910962/article/details/79595777
查看更多关于Spring使用注解和配置文件配置事务的详细内容...