HibernateTransactionManager 事务管理实现

本文深入探讨了HibernateTransactionManager的工作原理,介绍了如何通过SessionHolder和ThreadLocal实现事务与线程的绑定,以及doBegin()和doGetTransaction()方法的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HibernateTransactionManager对事务的实现,最终都是通过处理hibernate的Transaction的commit,rollback方法完成,

与单独的hibernate的Transaction事务没有太大的区别;但是,HibernateTransactionManager通过注入sessionfactory.

然后在得到session,把session包装成SessionHolder(),并通过threadlocal来对象的实现和线程的绑定(threadlocal实现重点)

最后到线程中的session取得的Transaction,

//SessionHolder对session包装,绑定到threadlocal中去
private final Map<Object, Session> sessionMap = Collections.synchronizedMap(new HashMap<Object, Session>(1));

1.主要理解这个类的doBegin(),doGetTransaction()方法

protected void doBegin(Object transaction, TransactionDefinition definition)

doBegin(Object transaction, TransactionDefinition definition)负责事务的创建

两个参数:

第一个参数:Object transaction

会得到session和一个connection.

设置HibernateTransactionObject,获取线程中的session和connection
protected Object doGetTransaction() {
		//这是一个SPI类,代表一个SessionHolder
		HibernateTransactionObject txObject = new HibernateTransactionObject();
                //在事务中设置保存点,是否允许嵌套事务
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		
		//在绑定的线程中查找当前的session,SessionHolder是session的包装,SessionHolder绑定到threadlocal
		SessionHolder sessionHolder =
				(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
		if (sessionHolder != null) {
			.......
			txObject.setSessionHolder(sessionHolder);
		}
		else if (this.hibernateManagedSession) {
			try {
				Session session = getSessionFactory().getCurrentSession();
				.......
				txObject.setExistingSession(session);
			}
			catch (HibernateException ex) {
				.......
			}
		}
                //得到一个connection,它也是和线程绑定的
		if (getDataSource() != null) {
			ConnectionHolder conHolder = (ConnectionHolder)
					TransactionSynchronizationManager.getResource(getDataSource());
			txObject.setConnectionHolder(conHolder);
		}

		return txObject;
	}

事务开始的地方

protected void doBegin(Object transaction, TransactionDefinition definition) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

		if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			throw new IllegalTransactionStateException(
				......

		Session session = null;
                //如果SessionHolder没有被创建,那么这里openSession并放到SessionHolder中去
		try {
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				Interceptor entityInterceptor = getEntityInterceptor();
				Session newSession = (entityInterceptor != null ?
						getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
				if (logger.isDebugEnabled()) {
					......
				}
				txObject.setSession(newSession);
			}
			//三种得到session(OpenSessionInView,getcurrentsession,opensession),这里就从SessionHolder得到session
			session = txObject.getSessionHolder().getSession();
			
			//设置<tx>isolation,read-only属性
			if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
				// We're allowed to change the transaction settings of the JDBC Connection.
				......
				Connection con = session.connection();
				Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
				txObject.setPreviousIsolationLevel(previousIsolationLevel);
			}
			else {
				// Not allowed to change the transaction settings of the JDBC Connection.
				......
			}

			if (definition.isReadOnly() && txObject.isNewSession()) {
				// Just set to NEVER in case of a new Session for this transaction.
				session.setFlushMode(FlushMode.MANUAL);
			}

			if (!definition.isReadOnly() && !txObject.isNewSession()) {
				// We need AUTO or COMMIT for a non-read-only transaction.
				FlushMode flushMode = session.getFlushMode();
				if (flushMode.lessThan(FlushMode.COMMIT)) {
					session.setFlushMode(FlushMode.AUTO);
					txObject.getSessionHolder().setPreviousFlushMode(flushMode);
				}
			}

			Transaction hibTx;

			// Register transaction timeout.
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
				// Applies to all statements, also to inserts, updates and deletes!
				hibTx = session.getTransaction();
				hibTx.setTimeout(timeout);
				hibTx.begin();
			}
			else {
				// Open a plain Hibernate transaction without specified timeout.
                                //创建并开始事务
				hibTx = session.beginTransaction();
			}

			// Add the Hibernate transaction to the session holder.
                        //把hibtx事务放到txobject里面,原因是因为这个SessionHolder会和线程绑定
			txObject.getSessionHolder().setTransaction(hibTx);

			// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
			if (getDataSource() != null) {
				Connection con = session.connection();
				ConnectionHolder conHolder = new ConnectionHolder(con);
				if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
					conHolder.setTimeoutInSeconds(timeout);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
				}
				TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
				txObject.setConnectionHolder(conHolder);
			}

			// Bind the session holder to the thread.
                        //如果是新的SessionHolder,把它和线程绑定
			if (txObject.isNewSessionHolder()) {
				TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
			}
                        //SessionHolder的状态标识,你的Transaction是一个线程中的session取得的
			txObject.getSessionHolder().setSynchronizedWithTransaction(true);
		}

		catch (Exception ex) {
			if (txObject.isNewSession()) {
				try {
					if (session.getTransaction().isActive()) {
						session.getTransaction().rollback();
					}
				}
				catch (Throwable ex2) {
					logger.debug("Could not rollback Session after failed transaction begin", ex);
				}
				finally {
					SessionFactoryUtils.closeSession(session);
				}
			}
			throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
		}
	}




### Spring 事务管理实现原理深入分析 Spring 的事务管理是一种高层次的抽象设计,其核心目标是通过声明式编程简化开发人员的工作负担。以下是对其内部工作原理的具体剖析: #### 1. **事务的核心概念** 事务是一组操作单元,要么全部成功执行,要么全部回滚到初始状态。Spring 提供了一种灵活的方式来定义这些操作的行为模式[^1]。 #### 2. **事务传播行为** 事务传播机制决定了多个事务方法之间的交互方式。默认情况下,`PROPAGATION_REQUIRED` 是最常用的传播行为,意味着如果当前存在事务,则加入该事务;如果没有则新建一个事务[^1]。这种灵活性由 Spring 完全控制,而非依赖于数据库本身。 #### 3. **启用事务支持** 在基于注解的方式下,开发者可以通过 `@EnableTransactionManagement` 或者自动配置(如 Spring Boot 中的 `DataSourceTransactionManagerAutoConfiguration`),激活事务管理功能[^2]。这一步会触发 AOP 切面代理的初始化,从而拦截带有 `@Transactional` 注解的方法调用。 #### 4. **事务管理器的作用** Spring 使用平台无关的接口 `PlatformTransactionManager` 来封装具体的事务逻辑。常见的实现有: - 对 JDBC 数据源的支持:`DataSourceTransactionManager` - 集成 Hibernate:`HibernateTransactionManager` 当应用程序启动时,Spring 将根据上下文中注册的 Bean 自动选择合适的事务管理器实例[^2]。 #### 5. **AOP 动态代理机制** 为了实现声明式的事务处理,Spring 借助 Aspect-Oriented Programming (AOP),即面向切面编程技术,在运行期动态生成代理对象。对于标注了 `@Transactional` 的业务服务层方法来说,每次调用都会被拦截并附加额外的操作——开启新事务、提交或者回滚现有事务等动作[^3]。 下面是一个简单的例子展示如何设置控制器和服务端点之间相互作用的同时也启用了事务特性: ```java @SpringBootApplication @RestController @RequestMapping("/api") public class SpringTransactionController { @Autowired private TransactionServiceA transactionServiceA; @RequestMapping("/spring-transaction") public String testTransaction() { try { transactionServiceA.methodA(); } catch (Exception e) { System.out.println("Error occurred during transaction processing."); throw new RuntimeException(e); } return "SUCCESS"; } } ``` 在此代码片段中,假设 `methodA()` 已经标记为具有事务属性,则无论何时访问 `/api/spring-transaction` 路径都将受到事务保护[^3]。 #### 6. **异常驱动的回滚策略** 只有遇到未被捕获的受检 (`Checked`) 和非受检 (`Unchecked`) 异常时,默认才会触发事务回滚。然而,也可以自定义哪些类型的错误应该引起撤销更改的机会。例如,可以指定某些特定 runtime exception 导致失败而其他继续完成正常流程[^1]。 --- ### 总结 综上所述,Spring 的事务管理体系不仅提供了强大的 API 支持多种持久化解决方案,而且借助 IoC/DI 及 AOP 技术极大地方便了日常项目中的数据一致性维护需求。理解以上几个方面有助于更好地掌握它的运作机理以及优化性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值