spring(五)--spring实现事务的一个小例子

        前两天给公司的数据库操作加了事务管理,今天博客就更一下这个吧。

        先说明:本文只是简单得实现一下事务,事务的具体内容,比如事务的等级,事务的具体实现原理等等。。。 菜鸟水平有限,暂时还更不了这个,以后的博客可能会涉及。

        如果您看完本博客之后能简单的实现一个事务,本文目的就达到了。

        首先简单通俗的解释一下啥叫事务: 在一个方法里的所有操作数据库的语句,要么全部执行(方法没有报错),要么全部不执行(方法抛错,已经执行的语句回滚)。

        xml形式实现事务,也是我在公司代码中实现的事务。他的好处是不用对现有代码进行任何修改,比较适合这种后期新加入的事务管理,缺点是可能会造成xml文件的庞大。

        下面是xml中各个信息:

<context:property-placeholder location="classpath:jdbc.properties" />

 该语句用于读取配置文件(数据库的用户名密码等)

<aop:config proxy-target-class="true"></aop:config>

 强制使用CGLIB代理(不知道为啥,不加这句我的代码会报错)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="defaultAutoCommit" value="true" />
		<property name="driverClassName" value="${driverClassName}" />
		<property name="url" value="${url}" />
		<property name="username" value="umetrip" />
		<property name="password" value="${password}" />
	</bean>

 数据源,不解释!

<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

 注册事务,并指定事务处理的数据源

<!-- 注册数据库操作类 -->
	<bean id="testDao" class="testSpring.business.Dao.iface.impl.TestDaoImpl">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<bean id="dbTest1" class="testSpring.business.transaction.DbTest1">
		<property name="testDao" ref="testDao" />
	</bean>

 

<aop:config>
		<aop:pointcut id="transactionPointcut"
			expression="execution(* testSpring.business.Dao.iface.impl..*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
	</aop:config>

 注册事务的切入点。可以看到,事务是利用spring中的面向切面,向方法中注入事务管理。

其中expression="execution(* testSpring.business.Dao.iface.impl..*.*(..))  :

 1、execution(): 表达式主体。

 2、第一个*号:表示返回类型,*号表示所有的类型。

 3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。

 4、第二个*号:表示类名,*号表示所有的类。

 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 如果方法是以get开头的方法,则不使用事务 -->
			<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED" />
			<!-- 类中所有其他方法都使用事务管理 -->
			<tx:method name="*" />
		</tx:attributes>
	</tx:advice>

    为事务指定管理者并配置事务信息。

    只需要配置xml文件即可,代码不用做任何修改。

  测试代码:

//读取配置文件(将配置文件中的bean加载进内存)
		ApplicationContext ctx = new ClassPathXmlApplicationContext("/testSpring/resources/applicationContext_transaction.xml");
		//获取的实例  
		DbTest1 bean = (DbTest1)ctx.getBean("dbTest1");  
		//调用方法  
		try{
			bean.test();
		}catch(Exception e){
			e.printStackTrace();
		}

    TestDaoImpl类:

package testSpring.business.Dao.iface.impl;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import testSpring.business.Dao.iface.ITestDao;
import testSpring.business.bean.TableBean;

/**  
 *  ITestDao.java : 
 * @author xuejupo  [email protected] 
 * create in 2016-2-16 下午5:04:56    
 */
public class TestDaoImpl implements ITestDao{

	private JdbcTemplate jdbcTemplate;
	
	public void setDataSource(DataSource dataSource){
		this.jdbcTemplate=new JdbcTemplate(dataSource);
	}
	
	@Override
	public void add(TableBean user) {
		// TODO Auto-generated method stub
		jdbcTemplate.update("insert into test values(?,?)", new Object[]{user.getId(),user.getName()});
		this.del(1);
		jdbcTemplate.update("delete from test where id = ?",new Object[]{213123,2});
	}
        @Override
	public void del(int id) {
		// TODO Auto-generated method stub
		jdbcTemplate.update("delete from test where id = ?",new Object[]{id});
	}
}

        多次修改TestDaoImpl类的add代码并执行结果发现:add方法如果抛出异常,那么add方法内所有的sql语句都会回滚。但是如果add方法内没有发生异常或者异常被处理,那么add方法已经执行的sql语句就会被提交。

        小结:

        1.事务是针对某一个方法的,只要是在这个方法内抛错,这个方法内的所有数据库操作全部回滚(比如上面类中add方法里的del方法也会回滚)。

        2.如果在进行事务管理的方法里将异常catch住并且写入log,而没有向外抛出,那么当前方法事务无效。。。解决方法是可以在写入log后向外抛出一个异常

        3.事务是很复杂的。。 不要看上面写的很简单。 比如事务的隔离等级,事务的锁表等级(行锁还是表锁,还有是否锁住索引等)。

        PS:如果您看到的不是ITEYE的博客(爬虫的僵尸博客),欢迎到我的博客跟我一起讨论:http://709002341.iteye.com/admin/blogs/2278348

猜你喜欢

转载自709002341.iteye.com/blog/2278348