package com.yw.spring.tx.annotation.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.yw.spring.tx.annotation.dao.BookShopDao;
import com.yw.spring.tx.annotation.exception.UserAccountException;
@Transactional //对当前类中所有的方法都起作用
@Service
public class BookShopServiceImpl implements BookShopService {
@Autowired
private BookShopDao bookShopDao ;
/**
* 事务属性:
* 1. 事务的传播行为 propagation: 一个事务方法被另外一个事务方法调用时,当前的事务如何使用事务.
* Propagation.REQUIRED 默认值. 使用调用者的事务.
* Propagation.REQUIRES_NEW 将调用者的事务挂起, 重新开启事务来使用.
* 2. 事务的隔离级别 isolation
* 1 读未提交 脏读
* 2 读已提交 不可重复读
* 4 可重复读 幻读
* 8 串行化 效率低。
*
* 3. 事务的回滚与不回滚 默认情况下, Spring会对所有的 运行时异常 进行事务回滚.
* rollbackFor
* rollbackForClassName
* noRollbackFor
* noRollbackForClassName
* 4. 事务的只读设置:
* readOnly
* true: 只读: 代表着只会对数据库进行读取操作,不会有修改的操作.
* 如果确保当前的事务只有读取操作,就有必要设置为只读,可以帮助数据库
* 引擎优化事务
* false: 非只读 不仅会读取数据还会有修改操作。 一定要设置false ,为了安全。默认是false.
*
* 5. 事务的超时设置: 设置事务在强制回滚之前可以占用的时间.
* timeout:
*
*/
//只对当前的方法起作用
@Transactional(propagation=Propagation.REQUIRES_NEW,
isolation=Isolation.READ_COMMITTED,
/* noRollbackFor={UserAccountException.class}*/
readOnly=false,
timeout=3)
public void buyBook(String username, String isbn) {
/*try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
Integer price = bookShopDao.findPriceByIsbn(isbn);
bookShopDao.updateStock(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.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.yw.spring.tx.annotation"></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>
<!-- NamedParameterJdbcTemplate -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>
<!-- 事务管理器 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启事务注解
transaction-manager 用来指定事务管理器, 如果事务管理器的id值 是 transactionManager,
可以省略不进行指定。
-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>