事务问题解决
用事務通知聲明式地管理事務
事務管理是一種橫切關注點
為了在 Spring 2.x 中啟用聲明式事務管理, 可以通過 tx Schema 中定義的 <tx:advice> 元素聲明事務通知, 為此必須事先將這個 Schema 定義添加到 <beans> 根元素中去.
聲明了事務通知后, 就需要將它與切入點關聯起來. 由于事務通知是在 <aop:config> 元素外部聲明的, 所以它無法直接與切入點產生關聯. 所以必須在 <aop:config> 元素中聲明一個增強器通知與切入點關聯起來.
由于 Spring AOP 是基于代理的方法, 所以只能增強公共方法. 因此, 只有公有方法才能通過 Spring AOP 進行事務管理.
用事務通知聲明式地管理事務示例代碼
用 @Transactional 注解聲明式地管理事務
除了在帶有切入點, 通知和增強器的 Bean 配置文件中聲明事務外, Spring 還允許簡單地用 @Transactional 注解來標注事務方法.
為了將方法定義為支持事務處理的, 可以為方法添加 @Transactional 注解. 根據 Spring AOP 基于代理機制, 只能標注公有方法.
可以在方法或者類級別上添加 @Transactional 注解. 當把這個注解應用到類上時, 這個類中的所有公共方法都會被定義成支持事務處理的.
在 Bean 配置文件中只需要啟用 <tx:annotation-driven> 元素, 并為之指定事務管理器就可以了.
如果事務處理器的名稱是 transactionManager, 就可以在<tx:annotation-driven> 元素中省略 transaction-manager 屬性. 這個元素會自動檢測該名稱的事務處理器.
<?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"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- 注解掃描 --><context:component-scan base-package="com.learn.spring.tx"></context:component-scan><!-- 配置數據源 --><!-- 引入外部化的配置文件 --><context:property-placeholder location="classpath:db.properties"/><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 配置jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 注入數據源 --><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事物管理器 --><bean id = "dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 基于注解使用事物,需要開啟事物注解. --><tx:annotation-driven transaction-manager="dataSourceTransactionManager"/></beans> package com.learn.spring.tx.service;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.learn.spring.tx.dao.BookShopDao; import com.learn.spring.tx.exception.UserAccountException;@Service //@Transactional //對該類中所有的方法都起作用 public class BookShopServiceImpl implements BookShopService{@Autowiredprivate BookShopDao bookShopDao ; @Transactionalpublic void buyBook(String username, String isbn) {try {Thread.sleep(5000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//1.查詢書的價格int price = bookShopDao.findBookPriceByIsbn(isbn);//2.更新書的庫存bookShopDao.updateBookStock(isbn);//3.更新用戶的余額bookShopDao.updateUserAccount(username, price); }// } package com.learn.spring.tx.test;import java.util.ArrayList; import java.util.List;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.spring.tx.service.BookShopService; import com.learn.spring.tx.service.Cashier;public class TestTransaction {private ApplicationContext ctx ;private BookShopService bookShopService ; @Testpublic void testBuyBook(){System.out.println(bookShopService.getClass().getName());bookShopService.buyBook("Tom", "1001");}}?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
- 上一篇: Spring事务管理介绍
- 下一篇: 事务的属性