通過給賬戶贈送積分的例子引入事務的話題:
未使用事務:
賬戶加減積分Dao:
public interface AccountDao {
void upScore(int score,int id);
void downScore(int score,int id);
}
賬戶加減積分實現類:
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public void upScore(int score, int id) {
getJdbcTemplate().update("update t_user set score = score + ? where id = ?", score,id);
}
@Override
public void downScore(int score, int id) {
getJdbcTemplate().update("update t_user set score = score - ? where id = ?", score,id);
}
}
public interface AccountService {
void sendScore(int senderId,int accepterId,int score);
}
賬戶贈送積分實現類:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
public void sendScore(int senderId, int accepterId, int score) {
accountDao.downScore(score, senderId);
accountDao.upScore(score, accepterId);
}
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.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 ">
<context:property-placeholder location="classpath:db.properties" />
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean name="accountDao" class="com.milan.transaction.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean name="accountService" class="com.milan.transaction.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-transaction.xml")
public class TestDemo {
@Resource(name="accountService")
private AccountService service;
@Test
public void test(){
service.sendScore(3, 4, 100);
}
}
說明:測試id爲3的賬戶給id爲4的賬戶充值100積分,測試通過。(圖略)
若sendScore方法過程報錯,則會造成只減積分,沒加積分的情況,故此添加spring事務處理
==========================================================
注意:以上代碼沒有添加事務
==========================================================
spring事務實現方式(一)
spring配置文件中添加:事務核心管理器,事務模板對象
<!-- 事務核心管理器,依賴於連接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事務模板對象 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
將賬戶Service實現類的sendScore方法添加事務處理:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
private TransactionTemplate template;
@Override
public void sendScore(int senderId, int accepterId, int score) {
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.downScore(score, senderId);
int i = 1/0;
accountDao.upScore(score, accepterId);
}
});
}
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public TransactionTemplate getTemplate() {
return template;
}
public void setTemplate(TransactionTemplate template) {
this.template = template;
}
}
spring事務實現方式(二)
spring配置文件:
<!-- 事務核心管理器,依賴於連接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事務模板對象 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!-- 配置事務通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
isolation:隔離級別
propagation:傳播行爲
read-only:是否只讀
-->
<tx:method name="sendScoreByXml" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<!-- 可以使用通配符*進行批量配置 -->
<tx:method name="add*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置織入 -->
<aop:config>
<aop:pointcut expression="execution(* com.milan.transaction.*ServiceImpl.*(..))" id="txPc"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
spring事務實現方式(三)
使用註解管理:
spring配置文件:
<!-- 開啓使用註解管理事務 -->
<!-- <tx:annotation-driven/> -->
Service實現類中添加@Transactional註解
@Override
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void sendScoreByHere(int senderId, int accepterId, int score) {
accountDao.downScore(score, senderId);
//int i = 1/0;
accountDao.upScore(score, accepterId);
}