SpringJDBC 事务控制

声明式事务(配置文件定义切面)

dao

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;
	}
}


service


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;
	}
}



test


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"/> 

在service类的上方添加@transaction 表示支持事务( 对声明式事务管理,Spring提供基于@Transactional注解方式来实现,但需要Java 5+。)
1 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
2 默认情况下,一个有事务方法, 遇到RuntiomeException 时会回滚 . 遇到 Checked Exception(受检查的异常) 是不会回滚 的. 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .

proxy-target-class:表示将使用的代码机制,默认false表示使用JDK代理,如果为true将使用CGLIB
  • 建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制是没问题,因为其使用基于接口的代理;而使用使用CGLIB代理机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”

混合事务管理最大问题在于如果我们使用第三方ORM框架,如Hibernate,会遇到一级及二级缓存问题,尤其是二级缓存可能造成如使用Spring JDBC和Hibernate查询出来的数据不一致等。

因此不建议使用这种混合使用和混合事务管理。



propagation:事务传播属性
isolation:事务隔离级别

http://jinnianshilongnian.iteye.com/blog/1442376
http://jinnianshilongnian.iteye.com/blog/1441271

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值