步骤:
引入jar包
spring-core相关jar包
spring-jdbc相关jar包
spring-aop相关jar包
xml方式实现声明式事务管理:
先创建一个Dept类
package cn.qblank.a_tx;
public class Dept {
private int deptId;
private String deptName;
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
然后写好对应的DeptDao类
package cn.qblank.a_tx;
import org.springframework.jdbc.core.JdbcTemplate;
public class DeptDao {
//容器注入jdbcTemplate对象
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void save(Dept dept){
String sql = "insert into dept(deptName) value(?) ";
jdbcTemplate.update(sql,dept.getDeptName());
}
}
DeptService类
package cn.qblank.a_tx;
public class DeptService {
//注入IOC容器
private DeptDao deptDao;
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
public void save(Dept dept){
deptDao.save(dept);
//发生异常,全部回滚
int i = 1/0;
}
}
写好jdbc的连接配置db.properties放在src目录下:
jdbc.user=root
jdbc.password=root
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///day09
jdbc.initPoolSize=5
jdbc.maxPoolSize=10
jdbc.maxStatements=100
jdbc.acquireIncrement=2
接下来就是关键的一部,使用spring配置连接配置信息,注入相关实例,并进行声明事务管理配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 1.加载配置文件db.properties -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.数据源配置 -->
<bean id="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>
<property name= "initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
<property name="maxStatements" value="${jdbc.maxStatements}"></property>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"></property>
</bean>
<!-- 3.jdbcTemplate实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.DeptDao实例 -->
<bean id="deptDao" class="cn.qblank.a_tx.DeptDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 5.DeptService实例 -->
<bean id="deptService" class="cn.qblank.a_tx.DeptService">
<property name="deptDao" ref="deptDao"></property>
</bean>
<!-- #############6. Spring声明式事务管理配置############### -->
<!-- 6.1配置事务管理类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 6.2配置事务增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 拦截的方法名 是否为只读 -->
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- AOP配置 -->
<aop:config>
<!-- 拦截该包下所有方法 -->
<aop:pointcut expression="execution(* cn.qblank.a_tx.DeptService.save(..))" id="pt"/>
<!-- 引入事务增强 引入切入点表达式 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
</beans>
最后我们再对其进行测试
package cn.qblank.a_tx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/qblank/a_tx/bean.xml");
Dept dept = new Dept();
dept.setDeptName("软件测试部");
DeptService deptService = (DeptService) ac.getBean("deptService");
deptService.save(dept);
System.out.println("添加成功");
ac = null;
}
}
运行结果:
数据库信息
由此看出,事务发生了回滚。
使用注解方式实现声明式事务管理
实体类对象和上面一样
接下来编写DeptDao类
package cn.qblank.anno;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository("deptDao")
public class DeptDao {
//容器注入jdbcTemplate对象
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
public void save(Dept dept){
String sql = "insert into dept(deptName) value(?) ";
jdbcTemplate.update(sql,dept.getDeptName());
}
}
LogDao类
package cn.qblank.anno;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository("logDao")
public class LogDao {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Transactional(propagation = Propagation.REQUIRED)
public void insertLog(){
jdbcTemplate.update("insert into t_deptLog(logName) value('插入一条dept表!!!')");
}
}
编写DeptService注解注入属性
package cn.qblank.anno;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DeptService {
//注入IOC容器
@Resource
private DeptDao deptDao;
@Resource
private LogDao logDao;
/**
* 事务控制
* @param dept
*/
public void saveLog(){
logDao.insertLog();
}
/**
* 保存
* @param dept
*/
@Transactional(
readOnly= false, //设置只读属性
timeout = -1, //设置不限时
isolation = Isolation.DEFAULT, //隔离级别:默认
propagation = Propagation.REQUIRED //数据库的传播行为
)
public void save(Dept dept){
deptDao.save(dept);
saveLog();
}
}
配置bean.xml文件,加载文件,配置数据源,注入jdbcTemplate实例,配置事务管理类,开启注解扫描,注解方式实现事务管理
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 1.加载配置文件db.properties -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.数据源配置 -->
<bean id="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>
<property name= "initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
<property name="maxStatements" value="${jdbc.maxStatements}"></property>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"></property>
</bean>
<!-- 3.jdbcTemplate实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.事务管理类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 5.开启注解扫描 -->
<context:component-scan base-package="cn.qblank.anno"></context:component-scan>
<!-- 6.注解方式实现事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
上面可以看到,我们再insertLog方法里面写了个异常,接下来我们来测试下是否回滚这个异常
首先弹出错误信息
接下来我们看看数据库是否发生回滚
可以发现数据库的数据并没有发生变化,所以我们回滚成功了!!!