zoukankan      html  css  js  c++  java
  • Spring事务管理

    Spring事务管理分为声明式事务管理编程式事务管理,声明式事务管理又分为xml注解两种配置方式。应该优先选择声明式事务,因为声明式事务对程序代码的影响最小,因此最符合非侵入式轻量级容器的理想 。只有在进行少量事务操作时,才应该选择编程式事务管理的方式。

    声明式事务管理

    xml配置方式

    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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
    		https://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- 导入数据库配置文件 -->
        <context:property-placeholder location="config.properties"/>
        
        <!-- 配置数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    		init-method="init" destroy-method="close">
    		<property name="driverClassName"><value>${jdbc_driverClassName}</value></property>
    		<property name="url"><value>${jdbc_url}</value></property>
    		<property name="username"><value>${jdbc_username}</value></property>
    		<property name="password"><value>${jdbc_password}</value></property>
    		<!-- ... -->
        </bean>
        
        <!-- 配置jdbcTemplate,使用jdbcTemplate操作数据库 -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        	<property name="dataSource" ref="dataSource"/>
        </bean>
        
        <bean id="userService" class="com.springdemo.tx.UserService">
        	<property name="jdbcTemplate" ref="jdbcTemplate"/>
        </bean>
        
        <!-- 配置事务管理器 -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!-- xml方式的配置声明式事务 start-->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
            <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.springdemo.tx.UserService.*(..))"/>
        </aop:config>
        <!-- xml方式的配置声明式事务 end-->
    </beans>
    

    config.properties:

    jdbc_driverClassName=com.mysql.jdbc.Driver
    jdbc_url=jdbc:mysql://192.168.1.77:3306/testdb?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
    jdbc_username=root
    jdbc_password=root
    

    UserService.java:

    public class UserService {
    	private JdbcTemplate jdbcTemplate;
    
    	public void addUser(String name, int age){
    		jdbcTemplate.update("insert into test007 (name,age) values (name,age)", name, age);
    	}
    	
    	public void updateUserName(String name, int id){
    		jdbcTemplate.update("update test007 set name=? where id=?", name, id);
    	}
    	
    	public void updateUserAge(int age, int id){
    		jdbcTemplate.update("update test007 set age=? where id=?", age, id);
    	}
    	
    	public void updateUser(String name, int age, int id){
    		updateUserName(name, id);
    		//模拟异常
    		Double.parseDouble("我不是Double,所以会抛出NumberFormatException异常");
    		updateUserAge(age, id);
    	}
    
    	public JdbcTemplate getJdbcTemplate() {
    		return jdbcTemplate;
    	}
    
    	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    		this.jdbcTemplate = jdbcTemplate;
    	}
    }
    

    main方法:

    public static void main(String[] args) {
    		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
    		UserService userService = (UserService) ac.getBean("userService");
    		userService.updateUser("小王", 18, 1);
    }
    

    使用注解方式

    Spring配置文件中添加:

    	<!-- 开启注解配置 -->
    	<tx:annotation-driven transaction-manager="txManager"/>
    

    然后在需要事务管理的方法上添加@Transactional注解

    	@Transactional
    	public void updateUser(String name, int age, int id){
    		updateUserName(name, id);
    		//模拟异常
    		Double.parseDouble("我不是Double,所以会抛出NumberFormatException异常");
    		updateUserAge(age, id);
    	}
    

    注意:注解方式和xml方式可以二选一,也可以结合使用,两者没有依赖关系。

    异常捕获和回滚

    异常捕获会导致事务机制失效,继而不会触发回滚。
    可以调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()手动回滚。

        @Transactional
    	public void updateUser(String name, int age, int id){
    		try{
    			updateUserName(name, id);
    			//模拟异常
    			Double.parseDouble("我不是Double,所以会抛出NumberFormatException异常");
    			updateUserAge(age, id);
    		}catch(NumberFormatException ex){
    			//手动回滚
    			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    			ex.printStackTrace();
    		}
    	}
    

    非RuntimeException时回滚

    Spring事务管理机制默认只在抛出RuntimeException时才会触发回滚,可以设置rollbackFor属性来指定其他类型的异常也能回滚。

        //rollbackFor指定抛出Exception类型异常时回滚
        @Transactional(rollbackFor=Exception.class)
    	public void updateUser(String name, int age, int id) throws Exception{
    		updateUserName(name, id);
    		if(id == 1){
    			throw new Exception("Id为1的用户不可修改");
    		}
    		updateUserAge(age, id);
    	}
    

    编程式事务管理

    修改Spring配置文件:

    	<bean id="userService" class="com.springdemo.tx.UserService">
        	<property name="jdbcTemplate" ref="jdbcTemplate"/>
        	<property name="transactionTemplate" ref="transactionTemplate"/>
        </bean>
        
        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> 
        	<property name="transactionManager" ref="txManager"/>
        </bean>
    	
    	<!-- 注释声明式事务管理配置 -->
    	<!-- <tx:annotation-driven transaction-manager="txManager"/>
        
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
            <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.springdemo.tx.UserService.*(..))"/>
        </aop:config> -->
    

    修改UserService:

    
        private TransactionTemplate transactionTemplate;
    
        public void updateUser(final String name, final int age, final int id){
    		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    		    protected void doInTransactionWithoutResult(TransactionStatus status) {
    		    	updateUserName(name, id);
    				//模拟异常
    				Double.parseDouble("我不是Double,所以会抛出NumberFormatException异常");
    				updateUserAge(age, id);
    		    }
    		});
    	}
    
        public TransactionTemplate getTransactionTemplate() {
    		return transactionTemplate;
    	}
    
    	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    		this.transactionTemplate = transactionTemplate;
    	}
    	
    
  • 相关阅读:
    python-进阶-优雅的python写法
    springMVC3学习(十一)--文件上传CommonsMultipartFile
    springMVC3学习(十)--注解式控制器
    CSS3/jQuery自定义弹出窗口
    window.open()详解及浏览器兼容性问题
    空格&nbsp在不同浏览器中显示距离不一致问题解决方法
    jQuery拖动调整表格列宽度-resizableColumns
    jQuery表格排序组件-tablesorter
    springMVC3学习(九)--redirect和forward跳转
    springMVC3学习(八)--全局的异常处理
  • 原文地址:https://www.cnblogs.com/seve/p/11172223.html
Copyright © 2011-2022 走看看