完整demo代码请到百度云下载:
dataSourceDemo2.rar
https://pan.baidu.com/s/1mhNCofI
**事务处理**
1.编程式事务
// 编程式事务 @Test public void test3(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-pool.xml"); DruidDataSource ds = (DruidDataSource) context.getBean("dataSource"); Connection con = null; Statement stmt = null; ResultSet result = null; try { con = ds.getConnection(); stmt = con.createStatement(); //关闭自动提交 con.setAutoCommit(false); String insertSql = "insert into eac_core_biz " + "(id, biz_system_id, biz_system_name, status_code, export, created_by, create_time, " + "updated_by, update_time) values (14, 'Test2', '帝景豪庭', 2, null, null, '2016-12-13 17:29:44', " + "null, '2016-12-13 17:29:44')"; //插入数据操作 stmt.executeUpdate(insertSql); //模拟异常出现 Assert.isTrue(false,"事务测试,模拟异常"); //更新数据操作 stmt.executeUpdate("update eac_core_biz set biz_system_id='efc' where id=14"); //事务提交 con.commit(); } catch (Exception e) { //事务回滚 try { con.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } }finally{ closeResultSet(result); closeStatement(stmt); closeConnection(con); } }
2.注解式事务
<!-- 定义数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/yun?characterEncoding=UTF8" /> <property name="username" value="root" /> <property name="password" value="centos" /> </bean> <!-- 定义JdbcTemplate的Bean --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"> </bean> <!-- 配置事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="txManager" /> <bean id="userDao" class="com.guo.dao.impl.UserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean>
接口 IUserDao
package com.guo.dao; import com.guo.entity.User; public interface IUserDao { void insertUser(User user); }
实现 UserDaoImpl
package com.guo.dao.impl; import java.sql.Types; import org.apache.log4j.Logger; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Transactional; import com.guo.dao.IUserDao; import com.guo.entity.User; @Transactional public class UserDaoImpl implements IUserDao { Logger LOGGER = Logger.getLogger(getClass()); private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void insertUser(User user) { String insertSql = "insert into student (ID, NAME, AGE) values (?,?,?)"; Object[] params = new Object[] { user.getId(),user.getName(),user.getAge() }; int[] types = new int[] { Types.INTEGER, Types.VARCHAR,Types.INTEGER }; int number = jdbcTemplate.update(insertSql, params, types); LOGGER.info("执行语句{insert into student (ID, NAME, AGE) values (?,?,?)},生效"+number+"条。"); //模拟异常出现 // Assert.isTrue(false,"事务测试,模拟异常"); } }
@Transactional 注解可用于实现类上,也可以放在具体的方法上。
3.spring aop 拦截器事务
<?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: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-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd "> <!-- 加载jdbc.properties --> <bean id="propertyConfigure" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath*:jdbc.properties</value> </list> </property> </bean> <!-- 定义数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 定义JdbcTemplate的Bean --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"> </bean> <!-- 配置事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"> </bean> <!-- 配置事物传播特性,(REQUIRED)是否存在事务,不存在则创建一个事务 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="merge*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="query*" read-only="true"/> <tx:method name="use*" read-only="true"/> <tx:method name="get*" read-only="true" /> <tx:method name="count*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="list*" read-only="true" /> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 切面,配置参与事务的类 --> <aop:config > <aop:pointcut id="allMethod" expression="execution(* com.guo.dao.impl.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethod" /> </aop:config> <bean id="userDao" class="com.guo.dao.impl.UserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="aopUserDao" class="com.guo.dao.impl.AopUserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> </beans>
测试方法
//aop配置事务 @Test public void test5(){ ApplicationContext context = new ClassPathXmlApplicationContext("aop-transaction.xml"); IUserDao userDao = (IUserDao) context.getBean("aopUserDao"); // User user = new User(); // user.setId(1); // user.setName("周星驰"); // user.setAge(33); // userDao.insertUser(user); User user = new User(); user.setId(2); user.setName("吴孟达"); user.setAge(35); userDao.insertUser(user); }
package com.guo.dao.impl; import java.sql.Types; import org.apache.log4j.Logger; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.Assert; import com.guo.dao.IUserDao; import com.guo.entity.User; public class AopUserDaoImpl implements IUserDao { Logger LOGGER = Logger.getLogger(getClass()); private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void insertUser(User user) { String insertSql = "insert into student (ID, NAME, AGE) values (?,?,?)"; Object[] params = new Object[] { user.getId(),user.getName(),user.getAge() }; int[] types = new int[] { Types.INTEGER, Types.VARCHAR,Types.INTEGER }; int number = jdbcTemplate.update(insertSql, params, types); LOGGER.info("执行语句{insert into student (ID, NAME, AGE) values (?,?,?)},生效"+number+"条。"); //模拟异常出现 // Assert.isTrue(false,"事务测试,模拟异常"); } }
4.当然在实际开发中会遇到很多的问题,如在使用AOP添加事务的时候,会出现嵌套事务,嵌套事务,内部事务回滚时,而外部事务并没有回滚,这个就需要我们按照实际的
情况来处理了,这个时候我们修改内部事务方法的名字,让他的事务不受控制,然而外部事务是存在的,这就保证了整个事务的完整。
或者使用编程式事务来控制整个事务,整个过程在程序中控制。