`
leiwuluan
  • 浏览: 697122 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

spring 事务管理

阅读更多

对于J2EE 应用程序而言,事务的处理一般有两种模式:

 

1 依赖特定事务资源的事务处理

这是应用开发中最常见的模式,即通过特定资源提供的事务机制进行事务管理。如通过JDBCJTA rollbackcommit方法;Hibernate Transaction rollbackcommit方法等。这种方法大家已经相当熟悉。

 

2 依赖容器的参数化事务管理

通过容器提供的集约式参数化事务机制,实现事务的外部管理。

 

Spring提供了一致的事务管理抽象。这个抽象是Spring最重要的抽象之一, 它有如下的优点:

 

(1)为不同的事务API提供一致的编程模型,如JTAJDBCHibernateiBATIS数据库层 JDO

(2)提供比大多数事务API更简单的,易于使用的编程式事务管理API

(3)整合Spring数据访问抽象

(4)支持Spring声明式事务管理

 

Spring事务管理能给我们带来什么?

对于传统的基于特定事务资源的事务处理而言(如基于JDBC 的数据库访问),Spring并不会对其产生什么影响,我们照样可以成功编写并运行这样的代码。同时,Spring还提供了一些辅助类可供我们选择使用,这些辅助类简化了传统的数据库操作流程,在一定程度上节省了工作量,提高了编码效率。

 

对于依赖容器的参数化事务管理而言,Spring 则表现出了极大的价值。Spring本身也是一个容器,只是相对EJB容器而言,Spring显得更为轻便小巧。我们无需付出其他方面的代价,即可通过Spring实现基于容器的事务管理(本质上来讲,Spring的事务管理是基于动态AOP)。

(1)编程式事务管理

使用TransactionTemplate

TransactionTemplate采用和其他Spring模板 ,如 HibernateTemplate一样的方法。它使用回调方法,把应用程序代码从处理取得和释放资源中解脱出来(不再有try/catch/finally)。如同 其他模板,TransactionTemplate是线程安全的。

 

示例:

 

UserDAO实现类

public class UserDAO implements IUserDAO {

    private TransactionTemplate transactionTemplate;

    private HibernateTemplate hibernateTemplate;

 

    public void setSessionFactory(

            SessionFactory sessionFactory) {

        this.transactionTemplate =

            new TransactionTemplate(

                    new HibernateTransactionManager(

                            sessionFactory)); 

        this.hibernateTemplate =

            new HibernateTemplate(sessionFactory);

    }

   

    public void insert(User user) {

        final User userData = user;

       

        transactionTemplate.setPropagationBehavior(

                TransactionDefinition.PROPAGATION_REQUIRED);

       

        transactionTemplate.execute(

          new TransactionCallbackWithoutResult() {

                protected void doInTransactionWithoutResult(

                        TransactionStatus status) {

                    try {

                        hibernateTemplate.save(userData);

                    }

                    catch(DataAccessException e) {

                        e.printStackTrace();

                        status.setRollbackOnly();

                    }

                }

            });

    }

 

    public User find(Integer id) {

        User user =

            (User) hibernateTemplate.get(User.class, id);

       

        return user;

    }

}

 

Test测试类

public class Test{

    public static void main(String[] args) {

        ApplicationContext context = new FileSystemXmlApplicationContext(

                    "beans-config.xml");

       

        IUserDAO userDAO =

            (IUserDAO) context.getBean("userDAO");

       

        User user = new User();

        user.setName("caterpillar");

        user.setAge(new Integer(30));

       

        userDAO.insert(user);

       

        user = userDAO.find(new Integer(1));

       

        System.out.println("name: " + user.getName());

    }

}

 

 

TransactionDefinition

隔离等级

描述

ISOLATION_DEFAULT

默认隔离等级

ISOLATION_READ_UNCOMMITTED

最低隔离等级,仅仅保证了读取过程中不会读取到非法数据

ISOLATION_READ_COMMITTED

某些数据库的默认隔离等级;保证了一个事务不会读到另外一个并行事务已修改但未提交的数据

ISOLATION_REPEATABLE_READ

比上一个更加严格的隔离等级。保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据

ISOLATION_SERIALIZABLE

性能代价最为昂贵,最可靠的隔离等级。所有事务都严格隔离,可视为各事务顺序执行

 

传播途径(Propagation Behavior)

 

Propagation Behavior

描述

PROPAGATION_REQUIRED

支持现有事务。如果没有则创建一个事务

 PROPAGATION_SUPPORTS

支持现有事务。如果没有则以非事务状态运行。

 PROPAGATION_MANDATORY

支持现有事务。如果没有则抛出异常。

 PROPAGATION_REQUIRES_NEW

总是发起一个新事务。如果当前已存在一个事务,则将其挂起。

PROPAGATION_NOT_SUPPORTED

不支持事务,总是以非事务状态运行,如果当前存在一个事务,则将其挂起。

 PROPAGATION_NEVER

 不支持事务,总是以非事务状态运行,如果当前存在一个事务,则抛出异常。

 PROPAGATION_NESTED

如果当前已经存在一个事务,则以嵌套事务的方式运行,如果当前没有事务,则以默认方式(第一个)执行

(2)声明式事务管理

Spring也提供了声明式事务管理。这是通过Spring AOP实现的。

 

大多数Spring用户选择声明式事务管理。这是最少影响应用代码的选择, 因而这是和非侵入性的轻量级容器的观念是一致的。

 

示例:

 

Spring配置文件

    <bean id="dataSource"

          class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName">

            <value>com.mysql.jdbc.Driver</value>

        </property>

        <property name="url">

            <value>jdbc:mysql://localhost:3306/test</value>

        </property>

        <property name="username">

            <value>root</value>

        </property>

        <property name="password">

            <value>root</value>

        </property> 

    </bean>

   

    <bean id="sessionFactory" 

          class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"

          destroy-method="close">

        <property name="dataSource">

            <ref bean="dataSource"/>

        </property>

        <property name="mappingResources">

            <list>

                <value>com/pojo/User.hbm.xml</value>

            </list>

        </property>

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">

                    org.hibernate.dialect.MySQLDialect

                </prop>

            </props>

        </property>

    </bean>

 

    <bean id="userDAO" class="com.dao.UserDAO">

        <property name="sessionFactory">

            <ref bean="sessionFactory"/>

        </property>

    </bean>

 

    <bean id="transactionManager"

          class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory">

            <ref bean="sessionFactory"/>

        </property>

    </bean>

       

    <bean id="userDAOProxy"

          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

        <property name="transactionManager">

            <ref bean="transactionManager"/>

        </property>

        <property name="proxyInterfaces">

            <list>

                <value>com.dao.IUserDAO</value>

            </list>

        </property>

        <property name="target">

            <ref bean="userDAO"/>

        </property>

        <property name="transactionAttributes">

            <props>

                <prop key="insert*">PROPAGATION_REQUIRED</prop>

            </props>

        </property>       

    </bean> 

 

UserDAO实现类

public class UserDAO implements IUserDAO {

    private HibernateTemplate hibernateTemplate;

   

    public void setSessionFactory(

            SessionFactory sessionFactory) {

        hibernateTemplate = new HibernateTemplate(sessionFactory);

    }

   

    public void insert(User user) {

        hibernateTemplate.save(user);

    }

 

    public User find(Integer id) {

        User user =

            (User) hibernateTemplate.get(User.class, id);

       

        return user;

    }

}

 

Test测试类

public class Test{

    public static void main(String[] args) {

        ApplicationContext context = new FileSystemXmlApplicationContext(

                    "beans-config.xml");

       

        IUserDAO userDAO =  (IUserDAO) context.getBean("userDAOProxy");

        User user = new User();

        user.setName("cater");

        user.setAge(new Integer(30));

       

        userDAO.insert(user);

       

        user = userDAO.find(new Integer(1));

       

        System.out.println("name: " + user.getName());

    }

}

 

 

配置中包含了dataSourcetransactionManager 等资源定义。这些资源都为一个名为userDAOProxy TransactionProxyFactoryBean 服务, userDAOProxy 则对包含实际数据逻辑的userDAO进行了事务性封装。

可以看到,在userDAOProxy "transactionAttributes"属性中,我们定义了针对userDAO 的事务策略,即将所有名称以insert 开始的方法(如UserDAO.insertUser方法)纳入事务管理范围。如果此方法中抛出异常,则Spring将当前事务回滚,如果方法正常结束,则提交事务。

而对所有名称以get 开始的方法(如UserDAO.getUser 方法)则以只读的事务处理机制进行处理。(设为只读型事务(readOnly),可以使持久层尝试对数据操作进行优化,如对于只读事务Hibernate将不执行flush操作,而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化)。

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics