Spring入门5.事务管理机制

Spring入门5.事务管理机制 20131126

 

代码下载 : 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t

回顾之前的知识,Spring 最为核心的两个部分IoC和AOP,我们已经学习过了,其中IoC是Spring的基础核心,AOP是建立在IoC之上的,难点是AOP的理解和配置方式。其实AOP编程是一种编程模型,他是站在动态的角度思考程序的运行过程。Spring本身通过IoC容器实现了AOP的思想,但是AspectJ是一种更加专业的主流的AOP编程思想的实现,他站在Java代码级别上去实现了AOP的编程思想,Spring借鉴了AspectJ的AOP,将他整合在Spring中,使用注解的方式于AspectJ的融合。

         这一节学习Spring中的事务管理:对于事务的理解就是整个操作时原子性的,要么全部做完,要么一点也不做。Spring对于事务处理有着良好的支持,Spring不仅提供了和底层事务员源无关的事物抽象,还提供了声明式事务,这样使代码开发人员从事务处理的底层代码中解脱出来,专注于业务的处理过程

1.Spring事务策略

         JavaEE中事务策略有全局事务局部事务。全局事务一般由应用服务器管理,需要底层应用服务器的JTA支持,EJB事务就是建立在JTA的基础之上,而JTA又需要通过JNDI获取,这样就意味着无论用户的应用是跨多个事务性资源的使用还是单一的事物性资源的使用,EJB都要求使用全局事务加以处理,这样基EJB的事务就无法脱离应用服务器的环境

         局部事务是基于单一事务性资源的,通常和底层的持久化技术有关,比如:当采取JDBC时,需要使用Connection对象操作事务;当使用Hibernate持久化技术的是偶,就需要使用session对象操作事务。当使用局部事务的时候,应用服务器不需要参与事务管理的,因此不保证扩多个事务性资源的事物的正确性,但是绝大多数的事物是基于单一事务性资源,只有很少的应用需要使用到多事务性资源的JTA事务。

         在单一事务性资源的情况之下,Spring直接使用底层的数据源管理事务。在面对多个事务性资源的时候,Spring会寻求JavaEE应用服务器的支持,通过引用服务器的JNDI资源完成JTA事务。(当然也可以脱离JavaEE应用服务器的支持使用JTA事务,比如使用JOTM项目,Spring也可以完成JTA的配置)

1.1PlatformTransactionManager

         Spring的事务策略是通过PlatformTransactionManager接口来体现的,该接口是Spring事务策略的核心,他根据TransactionDefinition提供的事务属性配置信息创建事务,并使用TransactionStatus来描述事务激活的状态。

         在PlatformTransactionManager接口中定义的方法,没有雨JNDI绑定,可以向Spring普通的bean一样对待PlatformTransactionManager的实现类,接口方法如下:

Transaction getTransaction(TransactionDefinition def);根据事务定义信息从事务环境中返回一个已经存在的事务,或者是创建一个新的事务,并且使用TransactionStatus来描述这个事务的状态。

void commit(TransactionStatus status);根据事务的状态提交事务,如果事务已经被标识为rollback-only,该方法将执行一个回滚事务的操作。

void rollback(TransactionStatus status);将事务回滚,当commit方法抛出异常的时候,rollback方法将会被隐式的调用,回滚事务。

         更进一步,Spring会将事务的管理委托给底层的持久化实现框架完成,因此Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类:

org.springframework.orm.jpa.JpaTransactionManager: 使用JPA进行持久化,使用这个事务管理器;

org.springframework.orm.hibernate3.HibernateTransactionManager:使用的是Hibernate3进行持久化,使用这一个事务管理器

org.springframework.jdbc.datasource.DataSourceTransactionManager使用Spring JDBC或者是iBatis等数据源的持久化技术,使用这一个事务管理器

org.springframework.orm.toplink.ToplinkTransactionManager: 使用Toplink进行持久化的时候使用

org.springframework.transaction.jta.JtaTransactionManager:具有多个数据源的全局事务使用

         这样就可以通过Spring提供的高级抽象对不同种类的事物实现相同方式的代理,而不必关心具体的实现。

1.2TransactionDefinition

         TransactionDefinition定义的Spring兼容的事务属性,这些属性对于事务管理的控制的若干方法进行配置没比如事务隔离级别、事务传播、事务超时和制度状态(都是新的名词,不要害怕,我也是第一次接触这些名词)

         事务隔离级别:当前的事物和其他事物的隔离程度。比如当前事务能否看到其他事物未提交的数据。TransactionDefinition定义的事务隔离级别:

ISOLATION_READ_UNCOMMITED:读未提交,一个事务在执行过程中可以看到其他事物没有提交的新插入记录,而且能够看到其他事务,没有提交对已有记录的更新。

ISOLATION_READ_COMMITED: 读已提交

ISOLATION_REPEATABLE_READ:可重复读,一个事务在执行过程中可以看到其他事务已经提交的新插入记录,但是不能够看到其他事务对已有记录的更新。

ISOLATION_SERIALIZABLE:序列化读,一个事务只可以操作在该事务提交之间已经提交的数据,并且可以在该事务中操作这些数据。

ISOLATION_DEFAULT:表示使用底层数据库默认的隔离级别。

         事务传播:一般在事务中执行的代码都会在当前事务中运行。但是如果一个事务上下文已经存在,有几个选项可以指定该事务性方法的执行行为。比如可以简单地在现有事务上下文中运行或者挂起现有事务,创建一个新的事务。

         Spring在TransactionDefinition接口中规定了7中类型的事务传播行为,它规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:

PROPAGATION_REQUIRED

PROPAGATION_SUPPORTS:

PROPAGATION_MANDATONRY

PROPAGATION_REQUIRES_NEW

PROPAGATION_NOT_SUPPORTED

PROPAGATION_NEVER

PROPAGATION_NESTED

         通过TransactionDefinition接口中的getPropagationBehavior()方法可以获得事务的传播性

         事务超时:表示事务在超时之前可以运行多久,也就是事务的最长续航时间。如果事务一直处于未提交或者是回滚状态,那么当超出时间的时候,事务将会自动回滚事务。通过TransactionDefinition接口中的getTimeout()获得事务的超时时间。

         只读状态:只读事务是不会修改任何数据的,只读事务对于优化十分重要,通过TransactionDefinition的isReadOnly()接口判断一个事务是否是只读的事务。

1.3TransactionStatus

         代表一个事务的运行状态。事务管理器通过该接口获得事务的运行期状态,也可以通过该接口间接的回滚事务,他相比于在抛出异常在回滚事务的方式更加具有可控性。

         boolean hasSavePoint()

         boolean isNewTransaction()

         boolean isCompleted(); 已经回滚或者是提交

         boolean isRollbackOnly();

         void setRolbackOnly()

         一点提醒:实际开发中对于PlatformTransactionManager、TransactionDefinition、TransactionStatus三个接口,开发者不会直接使用,而是通过配置的方式使用Spring提供的子类。了解这些知识点有利于帮助我们理解Spring中的事务机制。

 

2.使用XML的方式配置声明式事务

         事务管理的方式有两种:编程式和声明式。编程式事务管理需要在代码中手动编写和事务相关的操作代码,而对于声明式事务则无需再Java程序中编写任何和事务相关的代码。

         大多数的Spring选择的是声明式的事物管理功能,这种方式对于代码的侵入性比较小,可以让事务管理的逻辑完全从业务逻辑中移除,比较轻量级。Spring声明式事务管理是通过Spring AOP实现的,通过事务的声明性信息Spring负责将事务管理Advice逻辑动态织入到业务方法对应的连接点上。这些逻辑包括获取线程绑定资源、开始事务、提交回滚事务,进行异常转换等。

例子:以JDBC数据源为例

2.1配置数据源以及事务管理对象

         使用XML配置DBCP数据源,同时配置Spring提供的事物管理对象。

<!-- 数据源配置信息 -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

    <property name="driverClassName"    value="com.mysql.jdbc.Driver"/>

    <property name="url"                value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>

    <property name="username"           value="root"/>

    <property name="password"           value="221256"/>

    <property name="initialSize"        value="5"/>

    <property name="maxActive"          value="100"/>

    <property name="maxIdel"            value="30"/>

    <property name="maxWait"            value="1000"/>

</bean>

 

<!-- 事务管理器配置信息 -->

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    <property name="dataSource"         ref="dataSource"/>

</bean>

2.2配置事务的Advice

    在Spring中事务的Advice是有<tx:advice/>元素进行配置的。在该元素中,可以针对每一个方法或者是每一批方法配置事务的Advice

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

    xsi:schemaLocation="

        http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"

        default-lazy-init="true">

<tx:advice id="txAdvice" transaction-manager="txManager">

        <!-- 事务属性定义 -->

        <tx:attributes>

            <tx:method name="get*" read-only="true"/>

            <tx:method name="add*" rollback-for="Exception"/>

            <tx:method name="update*" />

            <tx:method name="del*"/>

        </tx:attributes>

    </tx:advice>

 

    在上述配置中,首先是引入命名空间的声明,然后使用<tx:advice>元素配置事务的Advice,在<tx:advice>中使用<tx:attributes>元素通过配置<tx:method/>子元素为一批方法指定所需要的语义,包括事务传播属性、事务隔离级别、事务超时等等。

    <tx:advice>中id是事务Advice的标识;transaction-manager是指定已经配置的事物管理器,如果事务管理器的id是transactionManager,则可以省略。配置<tx:advice>元素的重点是配置<tx:method>子元素,拓为一批方法指定了所需的事务原语,比如事务传播属性、事务隔离属性、事务超时属性、只读属性、对于指定异常回滚和指定异常不回滚,下面是<tx:method>的各种属性:

    name 可以使用通配符

    propagation 默认是REQUIRED,可选的值有REQUIRED SUPPRTS MANDATORY REQUIRES_NEW    NOT_SUPPORTED NEVER NESTED 表示的是传播

    isolation: 默认是DEFAULT 表示事务的隔离级别

    timeout defalur 是-1,单位秒,表示永不超时

    read-only: default false 只读事务,便于查询优化

    rollback-for: 所有运行期异常回滚,可以有多个Exception,逗号隔开

    no-rollback-for: 所有检查性异常不回滚

2.3配置事务增强切面

    通过事务Advice Aspect的配置实现方法级别的事务管理

    <!-- 通过AOP配置事务增强切面 -->

    <aop:config>

        <aop:pointcut expression="execution(* com.yang.service.USerService.*(..))" id="allMethods"/>

        <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethods"/>

    </aop:config>

    上述配置,配置了一个id是allMethods的切入点,匹配UserService下面的所有方法,然后使用一个<aop:advice>把切入点和事务增强txAdvice绑定在一起,当allMethods执行的时候,txAdvice定义的增强将被织入特定的连接点。

    其实在标准的AOP中是没有Advisor的概念的,Advisor实际上是表示的切面的概念,它同时包含横切代码和连接点信息。<aop:advisor>的作用就是讲增强和切入点绑定在一起,保证增强所包含的很企鹅逻辑在特定的连接点被织入。

2.4运行结果

    使用事务机制,向数据库中插入相同的两行记录,这样就会存在两行数据都无法出入导数据库中,体现事务的原子性操作。

UserDao.java

public interface UserDao {

    public void add();

}

UserDaoImpl.java

public class UserDaoImpl implements UserDao {

 

    DataSource dataSource;// 数据库连接接口,用于初始化JdbcTemplate,他是Spring中的JDBC的核心类之一

    public DataSource getDataSource(){

        return this.dataSource;

    }

    public void setDataSource(DataSource dataSource){

        this.dataSource = dataSource;

    }

    @Override

    public void add() {

        // 因为该函数是基于事务机制执行的,所以执行的时候会发生错误,两条记录都不会插入到数据库中。

        JdbcTemplate template = new JdbcTemplate(this.dataSource);

        template.execute("insert into user (id, username,password) values ( 3, 'yangtengfei','34567')");

        template.execute("insert into user (id, username,password) values ( 4, 'yangtengfei','456789')");     

    }

}

同时需要在applicationContext.xml配置文件中使用IoC的机制生命userDao和userService的Bean:

<!-- 配置UserService Class -->

    <bean id="userDao" class="com.yang.dao.impl.UserDaoImpl">

        <property name="dataSource" ref="dataSource"/>

    </bean>

   

    <bean id="userService" class="com.yang.service.impl.UserServiceImpl">

        <property name="userDao" ref="userDao"/>

    </bean>

代码整理:

UserDao.java//数据库的接口

UserDaoImpl.java//数据库接口实现类

UserService.java//用户的服务接口

UserServiceImpl.java//用户Service接口的实现类

applicationContext.xml//配置文件

TestMain.java//项目入口函数

同时需要添加JAR包的支持:Spring3 common mysql AspectJ的包。

最重要的是配置文件: 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: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.0.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"

        default-lazy-init="true">

    <aop:aspectj-autoproxy/>   

   

    <!-- 数据源配置信息 -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

        <property name="driverClassName"    value="com.mysql.jdbc.Driver"/>

        <property name="url"                value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>

        <property name="username"           value="root"/>

        <property name="password"           value="221256"/>

        <property name="initialSize"        value="5"/>

        <property name="maxActive"          value="100"/>

        <property name="maxIdle"            value="30"/>

        <property name="maxWait"            value="1000"/>

    </bean>

   

    <!-- 配置UserService Class -->

    <bean id="userDao" class="com.yang.dao.impl.UserDaoImpl">

        <property name="dataSource" ref="dataSource"/>

    </bean>

   

    <bean id="userService" class="com.yang.service.impl.UserServiceImpl">

        <property name="userDao" ref="userDao"/>

    </bean>

   

    <!-- 事务管理器配置信息 -->

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <property name="dataSource"         ref="dataSource"/>

    </bean>

   

    <tx:advice id="txAdvice" transaction-manager="txManager">

        <!-- 事务属性定义 -->

        <tx:attributes>

            <tx:method name="get*" read-only="true"/>

            <tx:method name="add*" rollback-for="Exception"/>

            <tx:method name="update*" />

            <tx:method name="del*"/>

        </tx:attributes>

    </tx:advice>

   

    <!-- 通过AOP配置事务增强切面 -->

    <aop:config>

        <aop:pointcut expression="execution(* com.yang.service.UserService.*(..))" id="allMethods"/>

        <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethods"/>

    </aop:config>

</beans>

 

YangTengfei

2013.11.27

 

转载于:https://www.cnblogs.com/hbhzsysutengfei/p/3473193.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux之路由知识之ip route 命令中的疑惑

1.基础知识 1.1 路由 &#xff08;Routing&#xff09; 1.1.1 路由策略 &#xff08;使用 ip rule 命令操作路由策略数据库&#xff09; 基于策略的路由比传统路由在功能上更强大&#xff0c;使用更灵活&#xff0c;它使网络管理员不仅能够根据目的地址而且能够根据报文大小、应…

python怎么执行程序_小鹅通视频怎么下载?用python实现小鹅通视频下载(二)

小鹅通视频怎么下载&#xff1f;用python实现小鹅通视频下载(二)背景上次分享《小鹅通视频怎么下载&#xff1f;用python实现小鹅通视频下载(一)[1]》后&#xff0c;引来了很多人咨询小鹅通视频怎么下载的问题。其实咨询的人大多是不懂python[2]语言的人&#xff0c;也有一部分…

在 Azure Functions 上使用不同的路由前缀

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Azure Tips and Tricks翻译&#xff1a;汪宇杰导语有时需要使用与 Azure Functions 自动生成的路由前缀不同的路由前缀。例如&#xff1a;https://mynewapimc.azurewebsites.net/api/HttpTriggerCSharp1 在函数名之前使用 api。…

RabbitMq、ActiveMq、ZeroMq、kafka之间的比较,资料汇总

2019独角兽企业重金招聘Python工程师标准>>> MQ框架非常之多&#xff0c;比较流行的有RabbitMq、ActiveMq、ZeroMq、kafka。这几种MQ到底应该选择哪个&#xff1f;要根据自己项目的业务场景和需求。下面我列出这些MQ之间的对比数据和资料。 第一部分&#xff1a;Rab…

linux之gdb基本调试命令和使用总结

1、gdb调试命令 描述backtrace(或bt)查看各级函数调用及参数finish连续运行到当前函数返回为止,然后停下来等待命令frame(或f) 帧编号选择栈帧info(或i) locals查看当前栈帧局部变量的值list(或l)列出源代码,接着上次的位置往下列,每次列10行list 行号列出从第几行开…

TMG学习(十一),保护企业内网上网安全

我们知道一个企业如果允许用户上网而且可以任意下载软件&#xff0c;这对于企业来说是非常危险的&#xff0c;用户无法辨别哪些是安全网站哪些网站存在风险&#xff0c;因此一旦用户在恶意网站上下载了软件&#xff0c;导致客户端中毒从而会影响整个企业内部网络&#xff0c;最…

sql跨表查询_跨表更新,看到自己写的SQL像个憨憨

有点 SQL 基础的朋友肯定听过 「跨表查询」&#xff0c;那啥是跨表更新啊&#xff1f;背景项目新导入了一批人员数据&#xff0c;这些人的有的部门名称发生了变化&#xff0c;有的联系方式发生了变化&#xff0c;暂且称该表为t_dept_members, 系统中有另外一张表 t_user_info 记…

iText创建一个含有中文的pdf文档

有朋友问我pdfbox支不支持向pdf文档中写入中文。然后试了好多遍都是有乱码&#xff0c;也找了好多资料没有找到解决办法。 但是在查找资料的过程中发现了另一个处理pdf的开源库iText.官方介绍 http://itextpdf.com/ 在这参考了两篇博客 博客1.pdfbox&iText生成PDF文件格式及…

万字长文 - 解读功能开关 | IDCF

原文&#xff1a;https://martinfowler.com/articles/feature-toggles.html作者&#xff1a;Pete Hodgson译者&#xff1a;冬哥功能开关Feature Toggle&#xff08;通常也称为功能标志Feature Flag&#xff09;是一种强大的技术&#xff0c;允许团队在不更改代码的情况下修改系…

linux c之gdb常用断点调试总结

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程 1 、安装GDB sudo apt-get install gdb 2 、怎么打断点 1 、源文件的某一行设置断点 break 行号 2、一个特定的函数设置断点 break 函数名 3、设置条件断点 break 行号 i…

2000多一件的大牌T恤,真实成本有多少?

▲ 点击查看喜大普奔&#xff0c;2021年度T恤大战总算是要在全国范围揭幕了。夏天的T恤永远不嫌多&#xff0c;基础款、印花款&#xff0c;从入春以来我们商城也陆陆续续上架了不少。但始终还有一些空白尚未填补&#xff0c;例如我们一直想给大家再找一些看起来上档次、穿起来显…

监控cacti中的RRDtool用法详解

RRDtool作为一个合格的运维工程师&#xff0c;监控技能必须是要掌握的&#xff0c;当然监控的软件很多很多(cacti,nagios,zabbix...)。而生产环境中一般只运用1、2种而已。所以全部掌握这些有点不靠谱。所以选择其中一种掌握之即可&#xff0c;当工作环境变化后还可以以之为跳板…

PHP学习第二天

今天&#xff0c;在昨天原有的代码基础上&#xff0c;经理讲述了一些新的东西&#xff0c;如果说昨天所讲的知识量是1&#xff0c;那么今天所讲的知识量便是3&#xff0c;其中还涉及到了一些变化&#xff0c;如将四个方格子变成一个居中的田字格。私以为&#xff0c;这便涉及到…

python生成静态库_使用boost.python静态库

编译脚本为&#xff1a;bjam stage toolsetmsvc linkstatic runtime-linkshared threadingmulti variantdebug,release --build-typecomplete --with-python注意这两个选项&#xff1a; linkstatic runtime-linkshared即&#xff1a;生成静态链接库&#xff0c;而运行时库链接C…

linux之使用indent格式化代码总结

1、介绍indent indent是一个整理代码的工具,不管你的代码写得多乱,你用indent工具都会把你的代码风格和linux 内核代码一致,基本上每个linux 发布都可以找到或者自己安装 sudo apt-get install indent 2、indent具体详细地址 比如在我的电脑上地址图片如下 所以地址在 /us…

cudaMalloc和cudaMallocPitch

原文链接 偶有兴趣测试了一下题目中提到的这两个函数&#xff0c;为了满足对齐访问数据&#xff0c;咱们平时可能会用到cudamallocPitch&#xff0c;以为它会带来更高的效率。呵呵&#xff0c;这里给出一段测试程序&#xff0c;大家可以在自己的机器上跑跑&#xff0c;你会发现…

使用 Dapr 缩短软件开发周期

Microsoft DevOps 文档里的文章&#xff08;https://docs.microsoft.com/zh-cn/azure/devops/report/dashboards/cycle-time-and-lead-time?viewazure-devops&#xff09;中的这张图片在给我们介绍了 什么是周期时间 以及它如何影响我的项目流时非常有影响力。第一次输入 &quo…

linux之写C代码出现warning: format not a string literal and no format arguments [-Wformat-security]

今天编写c语言代码的时候出现下面错误 解决办法&#xff1a; 把printf("length is %d" length);改成 printf("length is %d", length); 以后特么不要 像傻逼换这种错误&#xff0c;日来狗&#xff0c;写java代码写习惯了&#xff0c;不能动不动就是。