package com.ffcs.wlan.dao; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class RainDao { @Resource private JdbcTemplate jdbcTemplate; private Logger log = Logger.getLogger(RainDao.class); public void update1() { log.info("begin update1"); String sql= "UPDATE t_weak_password SET USER_ACCOUNT='ttt' where PWDSTR='111111'"; int updateCount = jdbcTemplate.update(sql); log.info("updayte1 count:" + updateCount); log.info("end update1"); } /** * dao模拟一个异常,异常必须要抛出去。如果不抛出去 外面的AOP不能捕获异常,事务不会回滚 * @throws Exception */ public void update2() throws Exception { log.info("begin update2"); try { String sql= "UPDATE1 t_weak_password SET USER_ACCOUNT='ooo' where PWDSTR='222222'"; int updateCount = jdbcTemplate.update(sql); log.info("updayte2 count:" + updateCount); } catch (Exception e) { log.error(e.getMessage()); throw e; } } public void select() { String sql= "select USER_ACCOUNT from t_weak_password"; List<Map<String, Object>> updateCount = jdbcTemplate.queryForList(sql); for (Map<String, Object> map : updateCount) log.info(map.get("USER_ACCOUNT")); } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } }
package com.ffcs.wlan.service; import javax.annotation.Resource; import org.springframework.stereotype.Service; import com.ffcs.wlan.dao.RainDao; @Service("rainService") public class RainService { @Resource private RainDao dao; /** * 要把异常抛出去。如果使用trycatch 捕获了异常,spring的AOP就无法捕获异常,事务就无法生效 * @throws Exception */ public void updateTest() throws Exception { dao.update1(); dao.update2(); dao.select(); } public void setDao(RainDao dao) { this.dao = dao; } }
package com.ffcs.wlan_jt; 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.AbstractJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.ffcs.wlan.service.RainService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath*:spring.xml","classpath*:spring-redis.xml","classpath*:spring-jdbc.xml" }) public class RainTest extends AbstractJUnit4SpringContextTests { @Resource private RainService servies; @Test public void update(){ try { servies.updateTest(); } catch (Exception e) { logger.error(e.getMessage()); } } public void setServies(RainService servies) { this.servies = servies; } }
<?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:tx="http://www.springframework.org/schema/tx" 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-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 配置数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="${jdbc_url}" /> <property name="username" value="${jdbc_username}" /> <property name="password" value="${jdbc_password}" /> </bean> <!-- 定义事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 注解方式配置事物 在service中@Transactional --> <!--<tx:annotation-driven transaction-manager="transactionManager" /> --> <!-- 拦截器方式配置事物--> <tx:advice id="transactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="append*" propagation="REQUIRED" /> <tx:method name="init" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="modify*" propagation="REQUIRED" /> <tx:method name="edit*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="delAndInit" propagation="REQUIRED" /> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="search*" propagation="REQUIRED" read-only="true" /> <tx:method name="datagrid*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <!-- 第一个*代表所有的返回值类型 ,第二个*代表所有的类,第三个*代表类所有方法,..代表所有的参数,(*sy.service..*Impl.*(..)) 包及子包" --> <aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* com.ffcs.wlan.service.*.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> </beans>
<!-- 用注解来实现事务管理 --> <tx:annotation-driven transaction-manager="transactionManager"/>
混合事务管理最大问题在于如果我们使用第三方ORM框架,如Hibernate,会遇到一级及二级缓存问题,尤其是二级缓存可能造成如使用Spring JDBC和Hibernate查询出来的数据不一致等。
因此不建议使用这种混合使用和混合事务管理。