spring配置總結——事務配置部分

Spring既支持編程式事務管理,也只支持聲明式事務管理。這篇直接上了尚硅谷的課件截圖。課時代碼比較倉促。

編程式事務管理:將事務管理代碼嵌入到業務方法中來控制事務的提交和回滾。在編程式事務時,必須在每個事務操作中包含額外的事務管理代碼。

聲明式事務管理:將事務管理代碼從業務方法中分離出來,以聲明的方式來實現事務的管理。事務管理作爲一種橫切關注點,可以通過AOP方法模塊化。Spring通過Spring AOP框架支持聲明式事務管理。

Spring中的事務管理器的不同實現:

org.springframework.jdbc.datasource.DataSourceTransactionManager:在應用程序中只需要處理一個數據源,而且通過JDBC存取。

org.springframework.transaction.jta.JtaTransactionManager:在JavaEE應用服務器上用JTA(Java Transaction API)進行事務管理

……

事務管理器以普通的Bean形式聲明在Spring IOC容器中。




使用註解的方式配置聲明式事務:

@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);
		
	}

}
@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 指定強制回滾之前事務可以佔用的時間。。如果服務運行時間超出timeout時間,強制回滾。
	//
	@Transactional(propagation=Propagation.REQUIRES_NEW,
			isolation=Isolation.READ_COMMITTED)
	@Override
	public void purchase(String username, String isbn) {
		//獲取書的單價
		int price = bookShopDao.findBookPriceByIsbn(isbn);
		//更新書的庫存
		bookShopDao.updateBookStock(isbn);
		//更新用戶餘額
		bookShopDao.updateUserAccount(username, price);

	}

}
<?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.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
	<context:component-scan base-package="com.atguigu.spring"></context:component-scan>
	<!-- 配置文件位置 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!-- 配置數據源 -->
	<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>
	
	<!-- 配置 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>
	
	<!-- 配置事務管理器 
		管誰的啊:管數據源的,所以加入DataSource
	-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 啓用事務註解 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

使用XML的方式配置聲明式事務:

public class BookShopDaoImpl implements BookShopDao {
	private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.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 querySql = "SELECT stock FROM book_stock WHERE isbn = ?";
		Integer stock = jdbcTemplate.queryForObject(querySql, 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 querySql = "SELECT balance FROM account WHERE username = ?";
		Integer balance = jdbcTemplate.queryForObject(querySql, Integer.class, username);
		if(balance < price){
			throw new UserAccountException("餘額不足");
		}
		String sql = "UPDATE account SET balance=balance-? WHERE username = ?";
		
		jdbcTemplate.update(sql, price ,username);
		

	}

}
public class BookShopServiceImpl implements BookShopService {
	private BookShopDao bookShopDao;
	public void setBookShopDao(BookShopDao bookShopDao) {
		this.bookShopDao = bookShopDao;
	}
	@Override
	public void purchase(String username, String isbn) {
		//獲取書的單價
		int price = bookShopDao.findBookPriceByIsbn(isbn);
		//更新書的庫存
		bookShopDao.updateBookStock(isbn);
		//更新用戶餘額
		bookShopDao.updateUserAccount(username, price);

	}

}
public class CashierImpl implements Cashier{
	@Autowired
	private BookShopService bookShopService;
	public void setBookShopService(BookShopService bookShopService) {
		this.bookShopService = bookShopService;
	}
	@Override
	public void checkout(String username, List<String> isbns) {
		for(String isbn: isbns)
			bookShopService.purchase(username, isbn);
		
	}

}
<?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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
	<!-- 配置文件位置 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!-- 配置數據源 -->
	<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>
	
	<!-- 配置 jdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置 NamedParameterJdbcTemplate,該對象可以使用具名參數,
		其沒有無參構造器,所以必須爲其構造器傳入參數
	-->
	<bean id="" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
		<constructor-arg ref="dataSource"></constructor-arg>
	</bean>
	
	<!-- 配置DAO -->
	<bean id="bookShopDao" class="com.atguigu.spring.tx.xml.dao.BookShopDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<!-- 配置Service -->
	<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. 配置事務管理器 
		管誰的啊:管數據源的,所以加入DataSource
	-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
		
	</bean>
	<!--2. 配置事務屬性 -->
	<tx:advice transaction-manager="transactionManager" id="txAdvice">
		<tx:attributes >
			<!-- 根據方法名指定事務的屬性 -->
			<tx:method name="purchase" propagation="REQUIRED"/>
			<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>






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章