千家信息网

spring中的事务是什么

发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,本篇内容主要讲解"spring中的事务是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring中的事务是什么"吧!1)spring的事务管理器:p
千家信息网最后更新 2025年02月23日spring中的事务是什么

本篇内容主要讲解"spring中的事务是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring中的事务是什么"吧!

1)spring的事务管理器:

package org.springframework.transaction;public interface PlatformTransactionManager {        TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;        void commit(TransactionStatus status) throws TransactionException;        void rollback(TransactionStatus status) throws TransactionException;}

2)spring的事务定义类:

package org.springframework.transaction;import java.sql.Connection;public interface TransactionDefinition {        // 事务的传播行为        int PROPAGATION_REQUIRED = 0;            // 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。                                                                                               int PROPAGATION_SUPPORTS = 1;            // 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。        int PROPAGATION_MANDATORY = 2;           // 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。        int PROPAGATION_REQUIRES_NEW = 3;        // 创建一个新的事务,如果当前存在事务,则把当前事务挂起。        int PROPAGATION_NOT_SUPPORTED = 4;       // 以非事务方式运行,如果当前存在事务,则把当前事务挂起。        int PROPAGATION_NEVER = 5;                       // 以非事务方式运行,如果当前存在事务,则抛出异常。        int PROPAGATION_NESTED = 6;                      // 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则等价于PROPAGATION_REQUIRED。                // 事务的隔离级别        int ISOLATION_DEFAULT = -1;                      // 使用底层数据库的默认隔离级别。        int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;        int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;        int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;        int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;        /**         * Use the default timeout of the underlying transaction system, or none if timeouts are not supported.         */        // 事务超时:指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。        // 默认为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。        int TIMEOUT_DEFAULT = -1;        int getPropagationBehavior();        int getIsolationLevel();        int getTimeout();        boolean isReadOnly();        String getName();}

3)spring中事务的回滚:

1)spring推荐以抛出异常的方式来回滚一个事务。2)spring事务管理器会捕捉任何未处理的异常,然后根据相应的配置来判断是否回滚抛出异常的事务。        1>默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。        2>可以配置在抛出哪些异常时回滚事务,包括checked异常;也可以明确设置哪些异常抛出时不回滚事务。

4)@Transactional注解

属性                                    类型                                                      描述value                                   String                          可选的限定描述符,指定使用的事务管理器propagation                             enum                               可选的事务传播行为设置isolation                               enum                               可选的事务隔离级别设置readOnly                                boolean                         读写或只读事务,默认读写timeout                                 int                                (in seconds granularity)事务超时时间设置rollbackFor                             (继承Throwable的)Class数组           导致事务回滚的异常类数组rollbackForClassName    (继承Throwable的)类名数组              导致事务回滚的异常类名字数组noRollbackFor                   (继承Throwable的)Class数组           不会导致事务回滚的异常类数组noRollbackForClassName  (继承Throwable的)类名数组              不会导致事务回滚的异常类名字数组用法:可以写在类(接口)上,也可以方法上。        1)当作用于类上时,该类的所有public方法将都具有该类型的事务属性。        2)可以在方法上使用该注解来覆盖类级别上的设置。        3)Spring建议不要在接口或接口方法上使用该注解,因为只有在使用基于接口的代理时它才会生效。        4)在private、protected、default的方法上使用该注解,则该注解将被忽略,也不会抛出任何异常。        5)默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是说:类内部方法调用本类内部的其它方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰!

5)原理:

1)spring的事务管理是通过spring的AOP(动态代理)来实现的。        spring中事务生效的一个前提:调用的方法必须被TransactionInterceptor拦截。                说明:只有通过TransactionInterceptor拦截的方法才会被加入到spring的事务管理中。                举例:                        在方法A中调用@Transactional修饰的方法B时,如果方法A与方法B在同一个类TestClass中,则加在方法B上的@Transactional注解不起作用,因为此时方法A对方法B的调用是不会被拦截器拦截的!                        解决办法:在方法A中,使用当前的代理对象来调用方法B。eg:((TestClass)AopContext.currentProxy()).B();2)对于正常的事务管理,必须关闭数据库的自动提交模式,spring会将底层连接的自动提交特性设置为false。        package org.springframework.jdbc.datasource;        public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {                private DataSource dataSource;                /**                 * This implementation sets the isolation level but ignores the timeout.                 */                [@Override](https://my.oschina.net/u/1162528)                protected void doBegin(Object transaction, TransactionDefinition definition) {                        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;                        Connection con = null;                        try {                                if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {                                        Connection newCon = this.dataSource.getConnection();                                        if (logger.isDebugEnabled()) {                                                logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");                                        }                                        txObject.setConnectionHolder(new ConnectionHolder(newCon), true);                                }                                txObject.getConnectionHolder().setSynchronizedWithTransaction(true);                                con = txObject.getConnectionHolder().getConnection();                                Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);                                txObject.setPreviousIsolationLevel(previousIsolationLevel);                                // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,                                // so we don't want to do it unnecessarily (for example if we've explicitly                                // configured the connection pool to set it already).                                if (con.getAutoCommit()) {                                        txObject.setMustRestoreAutoCommit(true);                                        if (logger.isDebugEnabled()) {                                                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");                                        }                                        con.setAutoCommit(false); // 【spring将底层连接的自动提交设置为false】                                }                                txObject.getConnectionHolder().setTransactionActive(true);                                int timeout = determineTimeout(definition);                                if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {                                        txObject.getConnectionHolder().setTimeoutInSeconds(timeout);                                }                                // Bind the session holder to the thread.                                if (txObject.isNewConnectionHolder()) {                                        TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());                                }                        }                        catch (Throwable ex) {                                DataSourceUtils.releaseConnection(con, this.dataSource);                                throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);                        }                }        }

6)配置文件:

1)注解的形式:        spring + mybatis:                说明:mybatis会自动参与到spring事务的管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,否则事务管理不起作用。                                                                                                                                                                                                                                      spring + hibernate:                                                                                                                                                                                   2)切面的形式:                                                                                                                                                                                                                                                                                 

到此,相信大家对"spring中的事务是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0