精华内容
下载资源
问答
  • 手动编程事务

    2020-03-05 10:28:05
    事务是spring框架中一个核心的模块,事务的ACID特性想必对于学习java的同学来说都不陌生,对于spring,实现事务的底层原理其实很简单,就是通过AOP代理进行实现,而实现spring的AOP更底层的,就是使用反射机制完成的...

    事务是spring框架中一个核心的模块,事务的ACID特性想必对于学习java的同学来说都不陌生,对于spring,实现事务的底层原理其实很简单,就是通过AOP代理进行实现,而实现spring的AOP更底层的,就是使用反射机制完成的;

    举例来说,当你的方法上标注了@Service之后,spring怎么知道你这个类会被纳入到整个bean的容器中进行管理呢?如果在这个类下面的某个方法上面加了@Transactionnal注解,spring怎么知道要为你的这个方法开启一个事务管理器呢?说到底,反射在这里就派上用场了,总体来说,就是通过反射,匹配类上的注解,再去匹配方法上的注解,只要找到了相应的注解,就开启相应的特性,就是这么简单,

    关于spring事务,常见的有两种,一种是编程式事务,比如java代码使用Jdbc进行数据库操作而没有引入其他框架时,就需要通过手动编写事务进行处理,另一种就是我们熟知的使用spring框架,帮助我们管理事务,比如像我们在xml配置文件中,通过配置扫描包和事务管理器,就可以对相关的类进行事务管理了,下面来演示一下采用编程式事务来学习一下spring的事务特性,了解了编程式事务,xml的事务就不是难事了。

    目录结构如下
    在这里插入图片描述
    maven配置:

     <properties>
    
            <spring.version>5.1.2.RELEASE</spring.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.6.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
            </dependency>
    
    
            <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.10</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
            <dependency>
                <groupId>com.mchange</groupId>
                <artifactId>c3p0</artifactId>
                <version>0.9.5.2</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.40</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>1.6.1</version>
            </dependency>
    
        </dependencies>
    

    spring配置:

    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
         http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd">
    
    
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.jiaxing"></context:component-scan>
    
        <!-- 开启事务注解 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
        <aop:config proxy-target-class="true"></aop:config>
    
        <!--数据库连接池配置 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver" />
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />
            <property name="user" value="test" />
            <property name="password" value="123456" />
        </bean>
    
    
        <!-- 2. JdbcTemplate工具类实例 -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!-- 事务管理器 -->
        <bean id="dataSourceTransactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <!-- 开启注解事务 -->
        <tx:annotation-driven transaction-manager="dataSourceTransactionManager" />
    
    
    </beans>
    
    

    编写接口:

    package com.jiaxing.dao;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Repository;
    
    /**
     * Description: 
     * Author: wgm
     * Date: 2020-03-05
     */
    @Repository
    public class UserDao {
    
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
    
        public void add(int id, String name) {
            String sql = "insert into a(id,name) values(?,?)";
            jdbcTemplate.update(sql, id, name);
        }
    
    
    }
    
    
    package com.jiaxing.service;
    
    import com.jiaxing.dao.UserDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * Description: 
     * Author: wgm
     * Date: 2020-03-05
     */
    @Service
    public class UserService {
    
    
        @Autowired
        private UserDao userDao;
    
    
        public void add() {
            userDao.add(1, "张三");
           // int i=1/0;
            System.out.println("添加成功+++++++++++++");
            userDao.add(2, "李四");
            System.out.println("添加成功+++++++++++++");
        }
    
    
    }
    
    

    使用AOP管理事务:

    package com.jiaxing.config;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
    import org.springframework.transaction.interceptor.TransactionAspectSupport;
    
    /**
     * Description: 
     * Author: wgm
     * Date: 2020-03-05
     */
    @Component
    @Aspect
    public class TransactionManagerUtils {
    
        @Autowired
        private DataSourceTransactionManager dataSourceTransactionManager;
    
    
        @Pointcut("execution(* com.jiaxing..*(..))")
        private void pointcut() {
        }
    
        //开启事务
        public TransactionStatus begin() {
            TransactionStatus status = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
            return status;
        }
    
        //提交事务
        public void commit(TransactionStatus status) {
            dataSourceTransactionManager.commit(status);
        }
    
        //事务回滚
        public void rollback(TransactionStatus status) {
            dataSourceTransactionManager.rollback(status);
        }
    
    
        @Around("pointcut()")
        private void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            TransactionStatus status = begin();
            proceedingJoinPoint.proceed();
            commit(status);
        }
    
        @AfterThrowing("pointcut()")
        private void error() {
            System.out.println("进入了异常通知++++++++++++++");
            TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
            dataSourceTransactionManager.rollback(transactionStatus);
        }
    
    
    }
    
    

    最后编写测试方法

    public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicayionContext.xml");
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
            System.out.println("连接成功");
    
        }
    

    需要注意的是,业务逻辑层如果使用了异常通知的话,不需要处理异常,只要向往抛出异常即可,如果处理了异常,遇到错误时,是不会进入异常通知方法,导致无法回滚事务,这时需要在catch里手动的回滚事务。

    展开全文
  • 日常开发中,Spring框架已经成为了主流必不可少的一部分,同样在事务处理上,Spring给我们提供了一致的事务管理抽象,这个抽象是Spring最重要的抽象之一,能实现为不同的事务Api提供一致的编程模型,本篇我们将从...

    a9401c2f05b94442cdaf7e04a8642e58.gif

    日常开发中,Spring框架已经成为了主流必不可少的一部分,同样在事务处理上,Spring给我们提供了一致的事务管理抽象,这个抽象是Spring最重要的抽象之一,能实现为不同的事务Api提供一致的编程模型,本篇我们将从事务开始学习Spring的事务抽象。

    事务

    事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

    为什么需要事务

    事务是为了解决数据安全操作提出的解决方案,事务的控制实际上就是控制数据的安全访问与隔离。举一个简单的例子:如果我们去银行转账,A账户将自己的1000元转账给B,那么业务实现的逻辑首先是将A的余额减少1000,然后往B的余额增加100,假如这个过程中出现意外,导致过程中断,A已经扣款成功,B还没来及增加,就会导致B损失了1000元,所以必须做出控制,要求A账户转帐业务撤销。这才能保证业务的正确性,完成这个操做就需要事务,将A账户资金减少和B账户资金增加放到同一个事务里,要么全部执行成功,要么全部撤销,这样就保证了数据的安全性。

    事务四大特性

    综上所述,要是满足之前的需求,事务必须要满足四大特性:

    1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。

    2) 一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。(实例:转账,两个账户余额相加,值不变。)

    3) 隔离性(isolation):一个事务的执行不能被其他事务所影响。

    4) 持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即便是在数据库系统遇到故障的情况下也不会丢失

    Java事务类型

    在Java中事务类型有三种:JDBC事务、JTA事务以及容器事务

    jdbc事务

    在jdbc中处理事务,都是通过connection完成,在同一事务中所有的操作,都在使用同一个connection对象完成,JDBC默认是开启事务的,并且默认完成提交操作。而在JDBC中有三种事务有关的操作:

    setAutoCommit:设置是否要自动提交事务,如果为true则表示自动提交,每一个sql独立存在一个事务,如果设置为false,则需要手动commit进行提交

    commit:手动提交事务

    rollback:手动回滚结束事务

    使用一个JDBC事务的基本步骤如下:

    @Test

    publicvoid testTX(){

    String url = "jdbc:mysql://127.0.0.1:3306/test";

    String username = "root";

    String password = "1234";

    String sourceUserId = "leo";

    String desUserId = "xnn";

    int money = 500;

    Connection connection = null;

    try{

    //1.加载数据库驱动程序

    Class.forName("com.mysql.jdbc.Driver");

    //获得数据库连接

    connection = DriverManager.getConnection(url, username, password);

    //开启事务

    connection.setAutoCommit(false);//如果为true的话,sql语句会分别执行,修改数据库;如果为false的话,会激活事务

    //多条数据操作数据

    Statement sql = connection.createStatement();

    sql.executeUpdate("UPDATE user_info SET balance = balance-"+ money + " WHERE user_id = '"+ sourceUserId+"'");

    sql.executeUpdate("UPDATE user_info SET balance = balance+"+ money + " WHERE user_id = '"+ desUserId+"'");

    //提交事务

    connection.commit();

    } catch(SQLException e) {

    e.printStackTrace();

    try{

    //回滚

    connection.rollback();

    }catch(SQLException ex){

    }

    } catch(ClassNotFoundException e) {

    e.printStackTrace();

    } finally{

    try{

    connection.close();

    } catch(SQLException e) {

    e.printStackTrace();

    }

    }

    }

    从代码中我们可以看出来JDBC事务的缺点:

    1. 冗长、重复

    2. 需要显示事务控制

    3. 需要显示处理受检查异常

    并且JDBC仅仅是为了完成事务操作提供了基础的API支持,通过操作JDBC我们可以将多个sql语句放到同一个事务中,保证ACID特性,但是当遇到跨库跨表的sql,简单的JDBC事务就无法满足了,基于这种问题,JTA事务出现了。

    JTA事务

    JTA(Java Transaction API)提供了跨数据库连接(或其他JTA资源)的事务管理能力。JTA事务管理则由JTA容器实现,J2ee框架中事务管理器与应用程序,资源管理器,以及应用服务器之间的事务通讯。

    JTA的构成

    在JTA中有几个重要的概念:

    1).高层应用事务界定接口,供事务客户界定事务边界

    2).X/Open XA协议(资源之间的一种标准化的接口)的标准Java映射 ,它可以使事务性的资源管理器参与由外部事务管理器控制的事务中

    3).高层事务管理器接口,允许应用程序为其管理的程序界定事务的边界范围

    JTA中的重要接口

    JTA中的重要接口主要位于javax.transaction包中

    1). UserTransaction:让应用程序得以控制事务的开始、挂起、提交与回滚等操作,由java或者ejb组件调用

    2). TransactionManager:用于应用服务管理事务的状态

    3). Transaction:用于控制执行事务操作

    4). XAResource:用于在分布式事务环境下,协调事务管理器和资源管理器的工作

    5). XID:用来为事务标示的java映射id

    需要注意的是前三个接口仅存在于 javaee.jar 中,在javaSe中并不存在。

    JTA事务编程的基本步骤

    我们来看下使用JTA事务的基本步骤,通过简单的java编码完成一个简单的JTA事务过程:

    //配置JTA事务,建立对应的数据源

    //1.建立事务:通过创建UserTransaction类的实例来开始一个事务

    Context ctx = newInitialContext(p) ;

    UserTransaction trans = (UserTransaction) ctx.lookup("javax. Transaction.UserTransaction");

    //开始事务

    trans.begin();

    //找到数据源,进行绑定

    DataSource ds = (DataSource) ctx.lookup("mysqldb");

    //建立数据库连接

    Connection mycon = ds.getConnection();

    //执行了sql操作

    stmt.executeUpdate(sqlS);

    //提交事务

    trans.commit();

    //关闭连接

    mycon.close();

    JTA事务的优缺点

    可以看出,JTA的优点很明显,提供了分布式下的事务解决方案,并且执行严格的ACID操作,但是,标准的JTA事务在日常开发中并不常用,其原因就是JTA的缺点导致的,例如JTA的实现相当复杂,JTA UserTransaction需要从JNDI获取,即我们如果要实现JTA一般情况下也需要实现JNDI,并且JTA只是个简易的容器,使用复杂,在灵活的需求下很难实现代码复用,因此我们需要一个能给我们进行完善容器事务操作的框架。

    Spring事务与事务抽象

    Spring给我们封装了一套事务机制,并且提供了完善的事务抽象,将事务所需要的步骤进行抽象划分,并以编程的方式提供一个标准API,如下:

    try{

    //1.开启事务

    //2.执行数据库操作

    //3.提交事务

    }catch(Exception ex){

    //处理异常

    //4.回滚事务

    }finally{

    //关闭连接,资源清理

    }

    c58222e91e3bdc3ec559dd3bff9cb68a.png

    Spring的事务抽象

    Spring的抽象事务模型基于接口PlatformTransactionManager ,该接口有不同的多种实现,每一种实现都有对应的一个特定的数据访问技术,大体如下:

    d17fd1ca35ed766e53659ffe2a36de34.png

    c369dd506c1658bc204b09c9f1584252.png

    可以看到,Spring并不是提供了完整的事务操作Api,而是提供了多种事务管理器,将事务的职责托管给了Hibernate、JTA等持久化机制平台框架来实现,而仅仅提供一个通用的事务管理器接口--org.springframework.transaction.PlatformTransactionManager ,并且给各大持久化事务平台框架提供了对应的事务管理器,用来限制其通用行为,但是具体事务实现将由各大平台自己去实现:

    PublicinterfacePlatformTransactionManager{  

      // 由TransactionDefinition得到TransactionStatus对象

    TransactionStatus getTransaction(TransactionDefinition definition) throwsTransactionException;

        // 提交

    Void commit(TransactionStatus status) throwsTransactionException;  

    // 回滚

    Void rollback(TransactionStatus status) throwsTransactionException;  

    }

    在Spring中使用各个事务

    接下来我们来看看,如果使用Spring事务抽象来使用各个事务平台,该如何使用:

    Spring JDBC事务

    如果应用程序中直接使用JDBC来进行持久化操作,可以使用 DataSourceTransactionManager来处理事务边界,而使用 DataSourceTransactionManager,你需要使用xml配置将其装配到应用上下文中:

    id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    name="dataSource"ref="dataSource"/>

    而配置完毕以后,在JDBC实例中, DataSourceTransactionManager是通过调用java.sql.Connection来管理事务 ,在sql所在的方法执行完毕以后,将会自动调用连接的commit()方法来提交事务,同样的如果执行过程中出现了异常,将会触发调用rollback()方法进行回滚 。

    Hibernate事务

    如果应用程序的持久化是通过Hibernate来实现的,那么你需要使用 HibernateTransactionManager,对于Hibernate3及以上版本,需要在Spring上下文定义中添加如下的Bean声明:

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

    name="sessionFactory"ref="sessionFactory"/>

    Java持久化Api事务--JPA

    事实上JPA规范的实现来自Hibernate,如果你打算使用JPA事务的话,你需要使用 JpaTransactionManager来管理事务,配置如下:

    id="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">

    name="sessionFactory"ref="sessionFactory"/>

    JpaTransactionManager只需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现),而 JpaTransactionManager将与由工厂所产生的JPA EntityManager 合作来构建事务。

    PlatformTransactionManager 及其相关属性

    事务管理器接口 PlatformTransactionManager通过getTransaction 方法来得到事务,参数为 TransactionDefinition类,而这个类定义类事务的基本属性:

    1. 传播行为

    2. 隔离规则

    3. 回滚规则

    4. 事务超时设置

    5. 事务是否只读

    而TransactionDefinition 接口的定义如下:

    publicinterfaceTransactionDefinition{

        int getPropagationBehavior(); // 返回事务的传播行为

        int getIsolationLevel(); // 返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据

        int getTimeout();  // 返回事务必须在多少秒内完成

    boolean isReadOnly(); // 事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的

    }

    其中最重要的是事务的传播行为以及隔离规则,我们先来看看事务的七种传播行为,如表格所示:

    PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中
    PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行
    PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常
    PROPAGATIONREQUIRESNEW新建事务,如果当前存在事务,把当前事务挂起
    PROPAGATIONNOTSUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
    PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常
    PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

    注:虽然有七种,但是其中三种都是Spring迭代留下的,一般我们只会配置REQUIRED和第四种REQUIRES_NEW 。

    事务隔离级别

    在看事务隔离级别前我们先来看看如果不进行事务隔离,所产生的 脏读、 不可重复读、 幻读效应是什么?

    脏读

    脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务获取数据进行操作,结果将刚刚未提交的数据获取到了。

    不可重复读

    不可重复读是指在一个事务内,多次读同一数据,前后读取的结果不一致。在A事务还没有结束时,另外一个事务B也访问该同一数据。那么,在A事务中的两 次读数据的过程中,由于B事务对当前数据进行修改操作,导致A事务两次读取的数据不一致,因此称为是不 可重复读。

    幻读

    幻读是指当事务不是独立执行时发生的一种现象,例如A事务对表中的一个数据进行了修改,这种修改涉及到表中的全部数据行。同时,B事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,就会发生操作A事务的用户发现表中还有没有修改的数据行,就好像 发生了幻觉一样。

    为了解决这些问题,Spring将事务分为了五个隔离级别,每个隔离级别分别对应的效果如下:

    DEFAULT使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的数据库隔离级别设置来决定隔离级别
    READ_UNCOMMITTED会出现脏读、不可重复读、幻读 ,同样并发效率最高
    READ_COMMITTED会出现不可重复读、幻读问题 (锁定当前读取的行数据)
    REPEATABLE_READ会出幻读(锁定读取的所有行)
    SERIALIZABLE会造成锁表,效率最差,但是不会出现任何脏读、幻读、不可重复读的情况

    注意:一般建议开启 READ_COMMITTED级别,即只读已经提交的数据,至于不可重复读和幻读问题,可以通过数据库乐观锁版本号方式解决。

    1be1967ae42fa68f4544ee3e361486da.png

    68144a03dd48089a5851af6af3608604.gif

     SpringCloud Alibaba之SentinelResource注解

     SpringCloud Alibaba之Sentinel的API实战

    ● SpringCloud Plus版本之SpringCloud Alibaba

    ● SpringCloud Alibaba之Nacos

     SpringCloud Alibaba之Nacos配置中心

    ● SpringCloud Alibaba之Nacos多环境多项目管理

    ● SpringCloud Alibaba之Nacos共享配置、灰度配置

     SpringCloud Alibaba之Nacos集群、持久化

    b93c0031a795bac292ae951b652ed738.png

    点击在看,驱动原创3cbe55b6126a1d0160dde2f815b81a94.gif

    展开全文
  • ### 手动完成事务管理```通过手动编写代码的方式完成事务的管理(不推荐)```### TransactionTemplate```为了简化事务管理的代码:提供了模板类 TransactionTemplate```### 手动完成事务管理的步骤```1. 配置事务管理器...

    ### 手动完成事务管理

    ```

    通过手动编写代码的方式完成事务的管理(不推荐)

    ```

    ### TransactionTemplate

    ```

    为了简化事务管理的代码:提供了模板类 TransactionTemplate

    ```

    ### 手动完成事务管理的步骤

    ```

    1. 配置事务管理器,Spring使用PlatformTransactionManager接口来管理事务,所以咱们需要使用到他的实现类

    ```

    ```

    2. 配置事务管理的模板

    ```

    ```

    3. 在需要进行事务管理的类中,注入事务管理的模板

    ```

    ```

    4. 在业务层使用模板管理事务

    // 注入事务模板对象

    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {

    this.transactionTemplate = transactionTemplate;

    }

    public void pay(final String out, final String in, final double money) {

    transactionTemplate.execute(new TransactionCallbackWithoutResult() {

    protected void doInTransactionWithoutResult(TransactionStatus status) {

    // 扣钱

    accountDao.outMoney(out, money);

    int a = 10/0;

    // 加钱

    accountDao.inMoney(in, money);

    }

    });

    }

    ```

    展开全文
  • Java编程中,以下示例使用connect.commit()方法来提交事务执行查询。假定数据库名称是:testdb,其中有两张表:employee和dept,employee表中有4条记录,dept表中有2条记录。创建数据库表的语句 -use testdb;-- 员工...

    在Java编程中,以下示例使用connect.commit()方法来提交事务执行查询。假定数据库名称是:testdb,其中有两张表:employee和dept,employee表中有4条记录,dept表中有2条记录。

    创建数据库表的语句 -

    use testdb;

    -- 员工表

    drop table if exists employees;

    create table if not exists employees (

    id int not null primary key,

    age int not null,

    name varchar(64),

    dept_id int(10)

    );

    INSERT INTO employees VALUES (100, 28, 'MaxSu', 1);

    INSERT INTO employees VALUES (101, 25, 'WeiWang', 2);

    INSERT INTO employees VALUES (102, 30, 'KidaSu', 2);

    INSERT INTO employees VALUES (103, 28, 'KobeBryant', 1);

    ----

    -- 部门表

    drop table if exists dept;

    create table if not exists dept (

    id int not null primary key,

    name varchar (64)

    );

    INSERT INTO dept VALUES (1, '技术部');

    INSERT INTO dept VALUES (2, '市场部');

    以下示例使用connect.commit()方法来执行提交事务和查询语句。

    package com.yiibai;

    import java.sql.*;

    public class CommitStatement {

    public static void main(String[] args) throws Exception {

    String JDBC_DRIVER = "com.mysql.jdbc.Driver";

    String DB_URL = "jdbc:mysql://localhost/testdb?useSSL=false";

    String User = "root";

    String Passwd = "123456";

    try {

    Class.forName(JDBC_DRIVER);

    } catch (ClassNotFoundException e) {

    System.out.println("Class not found " + e);

    }

    Connection con = DriverManager.getConnection(DB_URL, User, Passwd);

    con.setAutoCommit(false);

    Statement stmt = con.createStatement();

    String createTable = "CREATE TABLE `employees` ( `id` int(11) NOT NULL, `age` int(11) NOT NULL,`name` varchar(64) DEFAULT NULL,`dept_id` int(10) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;";

    String query = "insert into employees(id, name,age,dept_id) values(1,'Maxsu', 27, 1)";

    String query1 = "insert into employees(id, name,age,dept_id) values(5,'苏小牛', 24, 2)";

    String query2 = "select * from employees";

    // 创建表

    stmt.execute(createTable);

    con.commit();

    ResultSet rs = stmt.executeQuery(query2);

    int no_of_rows = 0;

    while (rs.next()) {

    no_of_rows++;

    }

    System.out.println("No. of rows before commit statement = " + no_of_rows);

    con.setAutoCommit(false);

    stmt.execute(query1);

    stmt.execute(query);

    con.commit();

    rs = stmt.executeQuery(query2);

    no_of_rows = 0;

    while (rs.next()) {

    no_of_rows++;

    }

    System.out.println("No. of rows after commit statement = " + no_of_rows);

    }

    }

    上述代码示例将产生以下结果。

    No. of rows before commit statement = 0

    No. of rows after commit statement = 2

    注:如果JDBC驱动程序安装不正确,将获得ClassNotfound异常。

    Class not found java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

    JDBC Class found

    SQL exception occuredjava.sql.SQLException: No suitable driver found for jdbc:mysql://localhost/testdb

    ¥ 我要打赏

    纠错/补充

    收藏

    加QQ群啦,易百教程官方技术学习群

    注意:建议每个人选自己的技术方向加群,同一个QQ最多限加 3 个群。

    展开全文
  • Spring事务管理Spring支持两种方式的事务管理:编程事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用,使用XML配置声明式事务: 推荐使用(代码侵入性最小),实际是通过AOP实现实现声明式事务...
  • Spring事务管理Spring支持两种方式的事务管理:编程事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用,使用XML配置声明式事务: 推荐使用(代码侵入性最小),实际是通过AOP实现实现声明式事务...
  • 我是国内某普通一本的自动化学生,我给自己的安排是走编程方向,大二到现在学过C,前端html,css,js,jq等,java,python,django,爬虫,数据结构,各种都学了一下,但是都不深,现在我想报一个培训班,人工智能,...
  • Spring事务事务传播行为 一、事务介绍 面试问: 什么是事务? 答:事务就是保证数据的一致性。 Spring事务 Spring事务传播行为 事务的隔离级别有也就是事务的特性? 1、原子:要么全部成功,要么全部失败。不...
  • 事务是spring框架中一个核心的模块,事务的ACID特性想必对于学习java的同学来说都不陌生,对于spring,实现事务的底层原理其实很简单,就是通过AOP代理进行实现,而实现spring的AOP更底层的,就是使用反射机制完成的...
  • 1、什么是(编程式)事务? 编程式(事务)就是(程序员)手动进行(事务管理),比如:JDBC中自己(手动将:数据提交到数据库)。 2、什么是(声明式)事务事务控制代码已经由 (spring 写好).程序员只需要...
  • Spring事务管理Spring支持两种方式的事务管理:编程事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用,使用XML配置声明式事务: 推荐使用(代码侵入性最小),实际是通过AOP实现实现声明式事务...
  • 转账案例需求:使用 spring 框架整合 DBUtils 技术,实现用户转账功能基础功能步骤分析:创建 java 项目,导入坐标编写 Account 实体类编写 AccountDao 接口和实现类编写 AccountService 接口和实现类编写 spring ...
  • 自己手动控制事务,就叫做编程事务控制。 Jdbc代码: Conn.setAutoCommite(false); // 设置手动控制事务 Hibernate代码: Session.beginTransaction(); // 开启一个事务 【细粒度的事务控制: 可以对指定的方法...
  • Java Spring-事务管理

    2019-10-06 21:06:30
    编程式的事务管理:手动编写代码 声明式的事务管理:只需要配置就可以 一、最初的环境搭建 public interface AccountDAO { public void out(String to,Double money); public void in(Strin...
  • Spring编程式和声明式事务实例讲解

    千次阅读 2018-05-23 14:20:54
    Java面试通关手册(Java学习指南):https://github.com/Snailclimb/Java_Guide ...编程事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用, 使用XML配置声明式事务: 推荐使用(代码侵入...
  • 七、ejb 编程事务管理(bean管理事务) 就是要程序员手动控制事务的开启、提交、回滚等操作。 避免使用的方法 在处于事务中时,不要调用 java.sql.Connection 或 javax.jms.Session 接口的 commit() 或 rollback()...
  • GitHub 17k Star 的Java工程师成神之路,不来...事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程事务和声明式事务两种。 关于事务的基础知识,如什么是事务,数据库事务以...
  • 七、ejb 编程事务管理(bean管理事务) 就是要程序员手动控制事务的开启、提交、回滚等操作。 避免使用的方法 在处于事务中时,不要调用 java.sql.Connection 或 javax.jms.Session 接口的 commit() 或 ...
  • 数据库的事务默认只支持单表的操作,如果有两个或以上的表需要同时修改时,需要设置事务手动提交、回滚。Java、Spring在遵循数据库事务的基础上提供了代码层面的实现。 Spring事务的两种使用方式: 1、在方法上...
  • 一,开启方法  正常情况下,事务的操作仅仅几行代码,如用注解将整个service包裹起来未免影响性能,如若手动开启事务,重复代码又过多,影响阅读 ... 通过对java1.8的预研,使用面向接口编程的方法,封装该...
  • 编程事务管理是侵入性事务管理,使用TransactionTemplate或者PlatformTransactionManager手动管理事务的提交、回滚等操作。声明式事务建立在AOP之上,原理是对方法进行拦截,在目标方法执行之前添加事务,目标方法...

空空如也

空空如也

1 2 3 4 5
收藏数 99
精华内容 39
关键字:

java手动编程事务

java 订阅