澳门新葡萄京娱乐场 3

澳门新葡萄京娱乐场SpringBoot+Mybatis事务管理

一、使用意况举个例子

在询问@Transactional怎么用事情未发生前大家一定要要先清楚@Transactional有何样用。上面举个栗子:比方二个机关中间有为数不菲成员,这五头分别保存在机构表和成员表里面,在剔除有些机构的时候,若是大家默许删除相应的成员。可是在执行的时候恐怕会并发这种景况,大家先删除部门,再删除成员,可是单位删除成功了,删除成员的时候出特别了。这时我们盼望假若成员删除退步了,从前剔除的机关也裁撤删除。这种景象就足以行使@Transactional事物回滚。

一、使用意况

在使用事务管理前,有须求先理解下应用途景。如实际进度中一个购入操作富含多个实行进度:查询仓库储存、下单、更新仓库储存,实操时,由于高并发存在,大概到下单结束时,更新仓库储存出错,那本次购买出售操作正是败退的,其下单结果应当被回滚。这种气象就要求引进事务调节,有限支撑整个操作的管事。

二、checked异常和unchecked异常

那边之所以让我们清楚checked分外和unchecked十分概念,是因为:

Spring使用证明式事务管理,暗中同意景况下,要是被讲解的数据库操作方法中发出了unchecked非凡,全部的数据库操作将rollback;若是发生的拾分是checked十分,暗许情况下数据库操作依然会提交的。

checked异常:

表示无效,不是前后相继中能够预测的。比方无效的客户输入,文件不设有,互连网只怕数据库链接错误。那几个都以外在的来头,都不是前后相继内部能够调控的。

总得在代码中显式地拍卖。譬如try-catch块管理,只怕给随处的法门加上throws表达,将异常抛到调用栈的上一层。

继承自java.lang.Exception(java.lang.RuntimeException除外)。

unchecked异常:

意味着错误,程序的逻辑错误。是RuntimeException的子类,例如IllegalArgumentException,
NullPointerException和IllegalStateException。

无需在代码中显式地捕获unchecked非常做拍卖。

继承自java.lang.RuntimeException(而java.lang.RuntimeException继承自java.lang.Exception)。

看下边包车型地铁极其构造图也许等级次序感更深些:

澳门新葡萄京娱乐场 1

二、配置形式

(1)配置applicationContext.xml

<!-- 事务管理器 -->
    <bean id="txManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 -->
    <tx:annotation-driven transaction-manager="txManager"/>

(2卡塔尔(قطر‎给现实作业方法增多证明

public class TestService {

    @Transactional("txManager")
    public void buy(){

        AuthenticationMapper authenticationMapper = MyApplicationContextUtil.getBean("authenticationMapper");

        int item_id = 2;
        // 查询指定书目状态
        Integer status = authenticationMapper.selectStatusOfItem(item_id);
        if (status == 1) {

            Integer count = authenticationMapper.insertOrder(item_id);

            if (count == 1) {

                authenticationMapper.updateStatus(item_id);

                throw new IllegalArgumentException("数据已存在,回滚");

            }
        }
    }
}

接下去,对buy方法做二个注解,该方式实现如下效果:

  • 1.书籍状态查询(select卡塔尔(قطر‎。
  • 2.可选购情状时,创造订单(insert卡塔尔。
  • 3.创新数据状态为不可购买(update卡塔尔(قطر‎。

其一历程不加事务调控时,恐怕会产出多少个主题材料,订单创造后,数据更新失利,招致那么些进程实施倒闭,就可以给数据库带给脏数据,这几个订单数量也未曾意思。所以那边通过工作调节来确认保证措施执行的一致性,进度中退步则回滚。

理当如此,Spring江西中华南理文高校程公司作回滚是有接触机制的,其触发机制正是抛出unchecked万分,即RuntimeException及其子类卓殊。即上述代码中的完结:

// 直接抛出即可回滚
throw new RuntimeException("数据已存在,回滚");

只是,假使是抛出checked十分,即必要在代码中显式地处理,比如try-catch块管理,或许给各省的诀要加上throws表明。对于那类格外,也要兑现回滚。既然已知其触发机制,人为创制触发点就能够,例如在catch中抛出unchecked格外。

try {
      throw new IOException("IO异常");
} catch (IOException e) {
      e.printStackTrace();
      throw new RuntimeException("数据已存在,回滚");
}

至于checked与unchecked卓殊分化后续补充,本文不开展。有关抛出RuntimeException,其实本人能够定义二个可怜类来管理。

public class MyException extends RuntimeException{

    public MyException(String message) {
        super(message);
    }
}

(3卡塔尔业务类注入bean

在beans.xml中添加testService的bean,交由Spring来统一保管业务对象,那样该对象方面包车型大巴职业才会收效。

 <bean id="testService" class="com.loongshawn.service.TestService"/>

假如职业对象是由此new发生的,即test瑟维斯未有挂号bean,数据库是不会进行回滚的,即如下:

TestService testService = new TestService();
testService.buy();

(4卡塔尔国业务测验

public void executeDeliveryTask() {

    TestService testService = MyApplicationContextUtil.getBean("testService");
    testService.buy();
}

运作结果:

[澳门新葡萄京娱乐场,图片上传失利…(image-7ade66-1515139853712卡塔尔(قطر‎]

数据库中未有脏数据插入。

三、@Transactional的施用实例

本实例采纳的是Eclipse+maven,maven只是作为jar管理,固然不打听的maven的猿友也足以读懂。

3.1、spring的布局文件

内部必得先配置tx名字空间如下:

澳门新葡萄京娱乐场 2

为了利用基于@Transactional的事务管理,需求在Spring中开展如下的构造:

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

    <tx:annotation-driven proxy-target-class="false" transaction-manager="appTransactionManager" />

博主的全体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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="  

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


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


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/context

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

     <!-- 引入jdbc配置文件 -->  
     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
               <value>classpath:properties/*.properties</value>
                <!--要是有多个配置文件,只需在这里继续添加即可 -->
            </list>
        </property>
    </bean>

    <!-- 配置数据源 -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- 不使用properties来配置 -->
        <!-- <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
            <property name="url" value="jdbc:mysql://localhost:3306/learning" /> 
            <property name="username" value="root" /> 
            <property name="password" value="christmas258@" /> -->
       <!-- 使用properties来配置 -->
        <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>

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

    <tx:annotation-driven proxy-target-class="false" transaction-manager="appTransactionManager" />

    <!-- 自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,这样就不用一个一个手动配置Mpper的映射了,只要Mapper接口类和Mapper映射文件对应起来就可以了。 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage"
            value="com.luo.dao" />
    </bean>

    <!-- 配置Mybatis的文件 ,mapperLocations配置**Mapper.xml文件位置,configLocation配置mybatis-config文件位置-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>  
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
        <!-- <property name="typeAliasesPackage" value="com.tiantian.ckeditor.model" 
            /> -->
    </bean>

    <!-- 自动扫描注解的bean -->
    <context:component-scan base-package="com.luo.service" />

</beans>

3.2、使用@Transactional,在丰硕顾客达成类方式加上注明

@Transactional(propagation=Propagation.REQUIRED)
public void addUser(User user) {
    userDao.addUser(user);
    String string  = null;
    if(string.equals("")) {
        int i = 0;
    }
}

上面的章程本人有意让其冒出空指针极度,会事物回滚

3.3、运营单元测验类

@Test  
public void addUserTest(){  
    User user = new User();
    user.setUserName("luoguohui1");
    user.setUserPassword("luoguohui1");
    userService.addUser(user);
}

察觉不能插入进去,可是一旦把@Transactional去掉,即代码如下,即便出现卓殊,但是数据库中依旧有增进对应数据的:

澳门新葡萄京娱乐场 3

3.4、源码下载

正文的工程是在mybatis入门(含实例教程和源码)的底工上改换的,该文包罗了数据库脚本及工程搭建的详尽流程。

正文最后源码下载:

三、事务属性

spring事务有7种传播行为,分别是:

  • 1、PROPAGATION.REQUIRED:假使当前还没职业,就创办一个新专门的学问,假如当前设有业务,就进入该业务,该装置是最常用的安装。

  • 2、PROPAGATION.SUPPORTS:扶持当前事情,假设当前设有业务,就投入该事情,倘若当前空头支票职业,就以非事务施行。

  • 3、PROPAGATION.MANDATOLANDY:协理当前事情,假诺当前设有业务,就加盟该业务,借使当前一纸空文职业,就抛出特别。

  • 4、PROPAGATION.REQUIRES_NEW:创立新工作,无论当前存海市蜃楼专门的学问,都创制新业务。

  • 5、PROPAGATION.NOT_SUPPORTED:以非事务情势实施操作,假若当前存在业务,就把近些日子事务挂起。

  • 6、PROPAGATION.NEVEEnclave:以非事务格局推行,假设当前留存业务,则抛出特别。

  • 7、PROPAGATION.NESTED:假设当前设有业务,则在嵌套事务内举行。就算当前尚无职业,则实行与PROPAGATION_REQUIRED相像的操作。

注明@Transactional暗许的流传行为是:PROPAGATION.REQUIRED

四、Spring中的@Transactional必供给打听的概念

Spring中的@Transactional基于动态代理的体制,提供了一种透明的事务管理机制,方便火速消除在付出中境遇的难题。

貌似选用是经过如下代码对章程或接口或类注释:

@Transactional(propagation=Propagation.NOT_SUPPORTED)

Propagation扶持7种不一致的扩散机制:

REQUIRED:假若存在一个工作,则支持当前专门的工作。如果未有事情则开启一个新的作业。

SUPPORTS:
假诺存在叁个专门的学问,支持当前专业。若无事情,则非事务的施行。不过对于事情同步的专门的学问微电脑,PROPAGATION_SUPPORTS与不选拔工作有有限不如。

NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的职业。

REQUIRESNEW:总是敞开三个新的事情。假使三个作业已经存在,则将那么些存在的事体挂起。

MANDATO奥迪Q7Y:即便已经存在二个工作,接济当前工作。若无四个运动的事务,则抛出相当。

NEVE奇骏:总是非事务地实行,若是存在一个运动工作,则抛出非常

NESTED:若是三个运动的事情存在,则运转在多个嵌套的事体中。若无挪动职业,则按REQUIRED属性施行。

上面是局地急需静心的事项,必得必需必看,不然境遇各类坑别说博主未有提醒您哦

上面是有的急需在意的事项,必需必需一定要看,不然蒙受种种坑别讲博主未有提示您哦

上面是有的亟需小心的事项,必须必得必看,不然遭逢种种坑别讲博主未有提示你啊

  • 在急需事务管理的地点加@Transactional 注脚。@Transactional
    注明能够被利用于接口定义和接口方法、类定义和类的 public 方法上。
  • @Transactional 评释只可以选用到 public 可以预知度的方法上。 假设您在
    protected、private 恐怕 package-visible 的法子上使用 @Transactional
    注解,它也不会报错,
    不过其一被讲授的点子将不会显得已安排的业务设置。
  • 专心仅仅 @Transactional 注脚的产出相差于展开事务行为,它独有是一种元数据。必得在陈设文件中应用安顿成分,才真的开启了职业行为。
  • 由此 成分的 “proxy-target-class”
    属性值来调整是基于接口的也许基于类的代理被创制。要是“proxy-target-class” 属值棉被服装置为
    “true”,那么依照类的代理将起效果(那时必要CGLIB库cglib.jar在CLASSPATH中)。倘使“proxy-target-class” 属值被装置为 “false”
    也许那么些脾性被略去,那么专门的职业的JDK基于接口的代办将起效果。
  • Spring团队提议在切切实实的类(或类的方法)上采取 @Transactional
    评释,而毫无使用在类所要达成的其余接口上。在接口上行使
    @Transactional
    评释,只好当您设置了基于接口的代办时它才生效。因为表明是 无法继承的,那就意味着如果正在利用基于类的代办时,那么事务的设置将不可能被基于类的代办所识别,何况对象也将不会被专门的学问代理所包装。
  • @Transactional 的业务开启 ,或然是依附接口的
    只怕是依赖类的代办被创建。所以在同多个类中二个措施调用另七个措施有事情的秘诀,事务是不会起效用的。

四、注意事项

  • 1、在急需事务管理的地点加@Transactional 表明。@Transactional
    评释能够被选择于接口定义和接口方法、类定义和类的 public 方法上。

  • 2、@Transactional 注脚只可以利用到 public 可以知道度的措施上。 倘使您在
    protected、private 恐怕 package-visible 的不二秘籍上选取 @Transactional
    申明,它也不会报错,
    但是其一被讲明的形式将不博览会示已计划的作业设置。

  • 3、注意仅仅 @Transactional 评释的产出相差于打开事务行为,它不过是一种元数据。必须在配置文件中接纳安顿成分,才真的敞开了事情行为。

  • 4、Spring团队提出在切实可行的类(或类的主意)上选用 @Transactional
    表明,而并不是使用在类所要完成的其余接口上。在接口上运用
    @Transactional
    注脚,只好当你设置了基于接口的代理时它才生效。因为表明是 无法继承的,那就表示假诺正在选择基于类的代理时,那么事务的安装将不可能被基于类的代办所识别,而且对象也将不会被专业代理所包装。

以上内容摘自网络,实际应用进程中,尽量只在切实工作类上增多@Transactional 注脚,做到技士只关心具体作业就能够。

五、大概特别

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: txManager,transactionManager
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
    at com.autonavi.service.TestService$$EnhancerBySpringCGLIB$$272f01cd.buy(<generated>)
    at com.autonavi.task.test.ScheduledTest.executeDeliveryTask(ScheduledTest.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

缓和方法:

亟待钦赐具体的东西微机,将要@Transactional改为@Transactional(“txManager”卡塔尔国,txManager为定义好的政工微处理机。

六、仿照效法资料

1、RuntimeException
API文档
2、Exception
API文档
3、Spring事务管理(详明+实例)
4、Interface
PlatformTransactionManager

初稿地址:http://blog.csdn.net/loongshawn/article/details/76944932

发表评论

电子邮件地址不会被公开。 必填项已用*标注