spring管理事务的方式
- 通过编码方式配置(了解)
- 通过xml文件配置aop方式配置(重要)
- 通过注解配置aop方式配置(重要)
spring配置事务步骤详解
通过xml文件配置aop方式配置(重要)
步骤
- 导入相应的jar包
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.log4j-1.2.15.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
mysql-connector-java-5.1.47.jar
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar
spring-beans-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar
spring-jdbc-4.2.4.RELEASE.jar
spring-test-4.2.4.RELEASE.jar
spring-tx-4.2.4.RELEASE.jar
- 书写相应实验测试方法
service接口类以及service实现类
//service层接口类
package com.geek.service;
public interface AccountService {
void transfer(Integer from,Integer to,Double money);
}
//service层实现类
package com.geek.service;
import com.geek.dao.AccountDao;
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
@Override
public void transfer(Integer from, Integer to, Double money) {
// TODO Auto-generated method stub
dao.decreaseMoney(from, money);
// 创造异常
// int i = 1/0;
dao.increaseMoney(to, money);
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
}
//dao层接口类
package com.geek.dao;
public interface AccountDao {
// 加钱
void increaseMoney(Integer id, Double money);
// 减钱
void decreaseMoney(Integer id, Double money);
}
//dao层实现类
package com.geek.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
//加钱
@Override
public void increaseMoney(Integer id, Double money) {
// TODO Auto-generated method stub
String sql = "update money set money = money+? where id = ? ";
getJdbcTemplate().update(sql,money,id);
}
@Override
public void decreaseMoney(Integer id, Double money) {
// TODO Auto-generated method stub
String sql = "update money set money = money-? where id = ? ";
getJdbcTemplate().update(sql,money,id);
}
}
- application.xml文件配置
将连接池放入spring容器
<!-- 1.将连接池放入spring容器 -->
<!-- 通过读取配置文件配置-->
<context:property-placeholder location="classpath:db.properties" />
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
事务核心管理器,封装了所有事务操作. 依赖于连接池
<!-- 2.事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
配置事务通知
<!-- 3.配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以方法为单位,指定方法应用什么事务属性
isolation:隔离级别
propagation:传播行为
read-only:是否只读
-->
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
配置织入
<!-- 4.配置织入 -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* com.geek.service.*Service.*(..))" id="txPc"/>
<!-- 配置切面 : 通知+切点
advice-ref:通知的名称
pointcut-ref:切点的名称
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
将accountDaoImpl放入spring容器
<!-- 5.将accountDaoImpl放入spring容器 -->
<bean name="accountDao" class="com.geek.dao.AccountDaoImpl" >
<property name="dataSource" ref="dataSource" ></property>
</bean>
将accountServiceImpl放入spring容器
<!-- 6.将accountServiceImpl放入spring容器 -->
<bean name="accountService" class="com.geek.service.AccountServiceImpl" >
<property name="dao" ref="accountDao" ></property>
</bean>
- 测试
package com.geek.test;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.geek.service.AccountService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext1.xml")
public class Dome1 {
@Resource(name = "accountService")
private AccountService service;
@Test
public void fun1() {
service.transfer(1, 2, 100d);
}
## ## ## }
通过注解配置aop方式配置(重要)
- 实现类和通过xml文件配置基本相同,直接进行application.xml配置文件的配置
<!-- 1.将连接池放入spring容器 -->
<context:property-placeholder location="classpath:db.properties" />
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
<!-- 2.事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3.开启注解配置事务 -->
<tx:annotation-driven/>
<!-- 4.将accountDaoImpl放入spring容器 -->
<bean name="accountDao" class="com.geek.dao.AccountDaoImpl" >
<property name="dataSource" ref="dataSource" ></property>
</bean>
<!-- 5.将accountServiceImpl放入spring容器 -->
<bean name="accountService" class="com.geek.service.AccountServiceImpl" >
<property name="dao" ref="accountDao" ></property>
</bean>
- 在service层实现类写入注解
package com.geek.service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.geek.dao.AccountDao;
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
@Override
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void transfer(Integer from, Integer to, Double money) {
// TODO Auto-generated method stub
dao.decreaseMoney(from, money);
//创造异常
//int i = 1/0;
dao.increaseMoney(to, money);
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
}
- 测试
package com.geek.test;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.geek.service.AccountService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Dome2 {
@Resource(name = "accountService")
private AccountService service;
@Test
public void fun1() {
service.transfer(1, 2, 100d);
}
}