zoukankan      html  css  js  c++  java
  • Spring(九)Spring对事务的支持

    一、对事务的支持

    事务:是一组原子操作的工作单元,要么全部成功,要么全部失败

    Spring管理事务方式:

    • JDBC编程事务管理:--可以控制到代码中的行

    可以清楚的控制事务的边界,事务控制粒度化细(编程的方式

    • JDBC声明事务管理---可以控制到方法

    事务相关API不用介入程序之中,将事务管理与实际业务代码解耦合(配置XML的方式)

    二、JDBC编程事务管理

    Spring提供两种方式实现编程式的事务管理:

    • 实现PlatformTransactionManager接口
    • 使用TransactionTemplate模式

    2.1、实现PlatformTransactionManager接口

    大致步骤:

    • 指定PlatformTransactionManager的实现类
    • 定义事务TransactionDefinition
    • 将事务定义传送给TransactionStatus
    • 将欲进行的事务用try..catch语句封起来
    • 如果事务出错,调用PlatformTransactionManager的rollback方法
    package com.pb.transaction.demo;
    
    import javax.sql.DataSource;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.DefaultTransactionDefinition;
    
    /**
     * 使用TransactionManager事务管理
     * 缺点:侵入代码
     * 优点:控制度细粒度
     */
    public class TransactionManagerDemo {
        
        public static void main(String[] args) {
        ClassPathXmlApplicationContext cpx=new ClassPathXmlApplicationContext("applicationContext.xml");    
        //获取platform对象
        PlatformTransactionManager ptm=(PlatformTransactionManager) cpx.getBean("transactionManager");
        //事务定义器
        DefaultTransactionDefinition dtd=new DefaultTransactionDefinition();
        //设置事务定义器的行为
        dtd.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        //事务状态通过事务管理器创建
        TransactionStatus ts=ptm.getTransaction(dtd);
        
        //进行事务
        
        try {
            //获取数据源
            DataSource ds=(DataSource) cpx.getBean("dataSource");
            //创建JDBCTemplacte
            JdbcTemplate jt=new JdbcTemplate(ds);
            //执行更新或者插入等操作
            jt.update("insert into person values(11,'TTM',23)");
            jt.update("update person set name='张王八' where id=7");
            ptm.commit(ts);
            
            System.out.println("===========");
        } catch (Exception e) {
            ptm.rollback(ts);
            System.out.println("撤消=======");
            e.printStackTrace();
        }
        
        }
    
    }

    2.2、使用TransactionTemplate模式

    大致步骤:

    • 需要封装一个TransactionManager
    • 创建事务回滚类
    • 执行TransactionManager的execute()方法
    package com.pb.transaction.demo;
    
    import javax.sql.DataSource;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.DefaultTransactionDefinition;
    import org.springframework.transaction.support.TransactionCallback;
    import org.springframework.transaction.support.TransactionCallbackWithoutResult;
    import org.springframework.transaction.support.TransactionTemplate;
    
    /**
     * 使用TransactionTemplate事务管理 缺点:侵入代码 优点:控制度细粒度
     */
    public class TransactionTeplateDemo {
    
        public static void main(String[] args) {
            ClassPathXmlApplicationContext cpx = new ClassPathXmlApplicationContext(
                    "applicationContext.xml");
            // 获取platform对象
            PlatformTransactionManager ptm = (PlatformTransactionManager) cpx
                    .getBean("transactionManager");
            // 事务模版
            TransactionTemplate tt = new TransactionTemplate(ptm);
            // 获取数据源
            DataSource ds = (DataSource) cpx.getBean("dataSource");
            // 创建JDBCTemplacte
            final JdbcTemplate jt = new JdbcTemplate(ds);
            // 进行事务回调函数
            tt.execute(new TransactionCallbackWithoutResult() {
    
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                    // 执行更新或者插入等操作
                    jt.update("insert into person values(17,'TOM',23)");
                    jt.update("update person set name='李四3' where id=4");
    
    
                }
            });
    
            
        }
    
    }

    2.3、编程事务配置

    <?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
    <!-- 声明数据源  org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->                    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!--驱动  -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <!--url  -->
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <!--用户名  -->
    <property name="username" value="accp"/>
    <!--密码  -->
    <property name="password" value="accp"/>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    </beans>

    三、JDBC声明事务管理

    主要通过AOP功能实现

    不需要修改原有的类

    使用TransationProxyFactoryBean指定要介入的事务以及方法

    实体类:数据库中有与之相对应的表

    package com.pb.entity;
    
    public class Person {
        private Long id;
        private String name;
        private Integer age;
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        
        
    }

    dao和实现类

    package com.pb.dao;
    
    import java.util.List;
    
    import com.pb.entity.Person;
    
    public interface PersonDao {
    
        public int insert(Person p);
        
        public int batchInsert(List<Person> persons);
        
    }
    //实现类
    package com.pb.dao.impl;
    
    import java.util.List;
    
    import javax.sql.DataSource;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    
    import com.pb.dao.PersonDao;
    import com.pb.entity.Person;
    
    public class PersonDaoImpl implements PersonDao {
        private JdbcTemplate jdbcTemplate;
        
        public void setDataSource(DataSource ds){
            jdbcTemplate=new JdbcTemplate(ds);
        }
        @Override
        public int insert(Person p) {
            String sql="insert into person values(?,?,?)";
            Object [] params={p.getId(),p.getName(),p.getAge()};
            return jdbcTemplate.update(sql,params);
        }
    
        @Override
        public int batchInsert(List<Person> persons) {
            int count=0;
            for (Person person : persons) {
                insert(person);
                count++;
            }
            return count;
        }
    
    }

    测试类

    package com.pb.transation.aop.demo;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.pb.dao.PersonDao;
    import com.pb.entity.Person;
    
    public class FirstAOPTransationDemo {
    
        public static void main(String[] args) {
            ClassPathXmlApplicationContext cpx=new ClassPathXmlApplicationContext("applicationContext.xml");    
            //这里调用代理的类
            PersonDao personDao=(PersonDao) cpx.getBean("personDaoProxy");
            
            Person p1=new Person();
            p1.setId(new Long(28));
            p1.setName("朱雀");
            p1.setAge(199);
            Person p2=new Person();
            p2.setId(new Long(29));
            p2.setName("玄武");
            p2.setAge(150);
            List<Person> persons=new ArrayList<Person>();
            persons.add(p1);
            persons.add(p2);
            int count=personDao.batchInsert(persons);
            System.out.println("更新了,"+count+"条记录");
            
        }
    
    }

    applicationContext.xml配置文件

    <?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
    <!-- 声明数据源  org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->                    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!--驱动  -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <!--url  -->
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <!--用户名  -->
    <property name="username" value="accp"/>
    <!--密码  -->
    <property name="password" value="accp"/>
    </bean>
    <!--接口实现类  -->
    <bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="personDaoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <!--指定接口  -->
    <property name="proxyInterfaces" >
    <list>
    <value>com.pb.dao.PersonDao</value>
    </list>
    </property>
    <!-- 管理的目标 -->
    <property name="target" ref="personDao"/>
    <!--注入事务管理  -->
    <property name="transactionManager" ref="transactionManager"></property>
    <!--事务管理的方法 和方式 -->
    <property name="transactionAttributes">
    <props>
    <prop key="batch*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>
    
    
    </beans>

    四、事务的属性

    声明式事务以方法为边界,简单的讲,一个方法被看成一个事务

    Spring中事务的属性:

    • 传播行为(Propagation Behavior)
    • 隔离级别(Lsolation Level)
    • 只读提示(Rean-only Hints)
    • 事务超时期限(The Transaction Timeout period)

    4.1、传播行为

    4.2、隔离级别

     

    五、Spring2.0后声明式事务管理:基于XMLSchema

    步骤:

    1. 加入相关的XML命名空间
    2. 使用<tx:advice>标签指定Advice
    3. 使用<aop:config>标签配置事务管理
    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
    
    <!-- 声明数据源  org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->                    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!--驱动  -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <!--url  -->
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <!--用户名  -->
    <property name="username" value="accp"/>
    <!--密码  -->
    <property name="password" value="accp"/>
    </bean>
    <!--接口实现类  -->
    <bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--事务管理的类  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--指明事务管理  -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--指定方法和方式  -->
    <tx:attributes>
    <tx:method name="batch*" propagation="REQUIRED"/>
    </tx:attributes>
    </tx:advice>
    <aop:config>
    <!--切入点  -->
    <aop:pointcut expression="execution(* com.pb.dao.PersonDao.*(..) )" id="mypoint"/>
    <!--关切入点和切入对象事务  -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
    </aop:config>
    </beans>

    六、基于注解的事务管理

    package com.pb.dao.impl;
    
    import java.util.List;
    
    import javax.sql.DataSource;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.pb.dao.PersonDao;
    import com.pb.entity.Person;
    //在要管理的类下加上@transactional
    @Transactional
    public class PersonDaoImpl implements PersonDao {
        private JdbcTemplate jdbcTemplate;
        
        public void setDataSource(DataSource ds){
            jdbcTemplate=new JdbcTemplate(ds);
        }
        @Override
        public int insert(Person p) {
            String sql="insert into person values(?,?,?)";
            Object [] params={p.getId(),p.getName(),p.getAge()};
            return jdbcTemplate.update(sql,params);
        }
        //在要管理的方法下加上属性propagation=Propagation.REQUIRED
        @Transactional(propagation=Propagation.REQUIRED)
        public int batchInsert(List<Person> persons) {
            int count=0;
            for (Person person : persons) {
                insert(person);
                count++;
            }
            return count;
        }
    
    }

    配置文件中加入一条

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
    
    <!-- 声明数据源  org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->                    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!--驱动  -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <!--url  -->
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <!--用户名  -->
    <property name="username" value="accp"/>
    <!--密码  -->
    <property name="password" value="accp"/>
    </bean>
    <!--接口实现类  -->
    <bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--事务管理的类  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--指明注解方式的事务管理器  -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
    </beans>
  • 相关阅读:
    JAVA与.NET的相互调用——通过Web服务实现相互调用
    WCF大数据量传输配置
    WCF大数据量传输解决方案
    C# #if DEBUG
    我对CSS vertical-align的一些理解与认识(一)
    htmlparser使用例子(全) 转载
    【HtmlParser】HtmlParser使用
    HTMLParser 使用详解
    htmlparser源码简单分析
    利用OpenXml生成Word2007文档
  • 原文地址:https://www.cnblogs.com/liunanjava/p/4419473.html
Copyright © 2011-2022 走看看