spring注解事物

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
com.tc.common.dao.BaseHibernateDao.getSession(BaseHibernateDao.java:67)
com.tc.common.dao.BaseHibernateDao.createCriteria(BaseHibernateDao.java:266)
com.tc.common.dao.BaseHibernateDao.find(BaseHibernateDao.java:248)
com.tc.common.dao.BaseHibernateDao.findBy(BaseHibernateDao.java:143)


出现这种异常是因为service层没加@Transactional所致
<think>我们正在讨论Spring事务注解(@Transactional)的工作原理。根据引用内容,Spring事务分为声明式和编程式,而注解属于声明式事务管理。其核心原理是AOP(面向切面编程)和代理机制。 ### 1. 核心机制:AOP代理 当你在方法或类上添加`@Transactional`注解时,Spring会在运行时为该Bean创建代理对象。这个代理对象会拦截所有带有`@Transactional`注解的方法调用,并在方法执行前后加入事务管理逻辑(开启事务、提交事务、回滚事务)[^2][^3]。 ### 2. 事务管理器的角色 Spring本身并不直接管理事务,而是通过`PlatformTransactionManager`接口委托给具体的事务管理器实现(如JDBC的`DataSourceTransactionManager`、JPA的`JpaTransactionManager`、JTA的`JtaTransactionManager`等)。在Spring Boot中,`@EnableTransactionManagement`会自动根据项目依赖配置事务管理器[^4]。 ### 3. 事务拦截流程 当一个被`@Transactional`注解的方法被调用时: 1. **代理拦截**:代理对象拦截方法调用。 2. **获取事务**:事务管理器根据事务属性(如传播行为、隔离级别等)获取或创建一个事务(可能是一个新事务,也可能是加入现有事务)。 3. **执行业务逻辑**:在事务上下文中执行原始方法。 4. **处理异常**:如果方法抛出异常,事务管理器会根据回滚规则(默认只回滚`RuntimeException`和`Error`)决定是否回滚事务。若未抛出异常或抛出的异常类型不需要回滚,则提交事务[^3]。 ### 4. 关键配置属性 `@Transactional`注解支持以下属性配置: - `propagation`:事务传播行为(例如:REQUIRED、REQUIRES_NEW)。 - `isolation`:事务隔离级别(例如:READ_COMMITTED)。 - `timeout`:事务超时时间。 - `readOnly`:是否只读事务(优化性能)。 - `rollbackFor`/`noRollbackFor`:指定回滚/不回滚的异常类型[^3]。 ### 5. 注意事项 - **方法可见性**:`@Transactional`注解只能应用于`public`方法。如果应用于`protected`、`private`或包可见方法,事务不会生效(因为代理无法拦截非public方法)[^3]。 - **自调用问题**:在同一个类中,一个非事务方法调用另一个`@Transactional`方法时,事务不会生效(因为自调用不会经过代理对象)。需要通过AspectJ或注入自身代理解决[^2]。 ### 示例代码 ```java @Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void createUser(User user) { userRepository.save(user); // 此操作在事务中执行 if (someCondition) { throw new RuntimeException("回滚事务"); // 触发回滚 } } } ``` ### 总结 Spring事务注解通过**AOP代理**和**事务管理器**协作实现。代理负责拦截方法调用并管理事务边界,事务管理器负责底层事务操作(如JDBC连接的事务控制)。理解代理机制和事务属性配置是掌握Spring事务的关键[^2][^3][^4]。 --- **相关问题** 1. **Spring事务的传播行为有哪些?如何选择?** (解释`REQUIRED`、`REQUIRES_NEW`等传播行为的区别和适用场景) 2. **如何解决Spring事务自调用失效的问题?** (探讨AspectJ、代理注入等解决方案) 3. **Spring Boot中如何配置多数据源的事务管理?** (涉及`@Primary`、`@Qualifier`注解和`ChainedTransactionManager`的使用) 4. **Spring事务回滚规则有哪些?如何自定义回滚异常类型?** (分析`rollbackFor`/`noRollbackFor`属性的用法) 5. **声明式事务和编程式事务应该如何选择?** (对比两种事务管理的优缺点及适用场景)</think>Spring事务注解(`@Transactional`)的工作原理基于**AOP代理机制**和**事务管理器协作**实现,其核心实现流程如下: ### 一、核心实现机制 1. **代理对象创建** Spring容器在初始化Bean时,检测到`@Transactional`注解后,会通过AOP(面向切面编程)创建该Bean的**代理对象**(JDK动态代理或CGLIB代理)。 ```java // 原始Bean public class UserService { @Transactional public void updateUser(User user) { ... } } // Spring创建的代理对象(伪代码) public class UserServiceProxy extends UserService { private TransactionManager txManager; public void updateUser(User user) { // 1. 开启事务 // 2. 调用原始方法super.updateUser() // 3. 提交/回滚事务 } } ``` 2. **事务拦截器工作流程** 代理对象通过`TransactionInterceptor`拦截目标方法,按顺序执行: ```mermaid graph TD A[方法调用] --> B{是否有@Transactional} B -->|是| C[获取事务管理器] C --> D[开启事务<br>PlatformTransactionManager.getTransaction] D --> E[执行业务逻辑] E --> F{是否抛出异常?} F -->|是| G[回滚事务<br>txManager.rollback] F -->|否| H[提交事务<br>txManager.commit] ``` ### 二、关键组件协作 1. **事务管理器(PlatformTransactionManager)** Spring Boot根据依赖自动配置: - JDBC → `DataSourceTransactionManager` - JPA → `JpaTransactionManager` - 分布式事务 → `JtaTransactionManager`[^4] 2. **事务属性解析** 注解属性被解析为`TransactionAttribute`对象: | 属性 | 默认值 | 作用 | |---|---|---| | `propagation` | REQUIRED | 事务传播行为 | | `isolation` | DEFAULT | 事务隔离级别 | | `rollbackFor` | RuntimeException | 触发回滚的异常类型 | | `timeout` | -1 | 事务超时时间(秒) | | `readOnly` | false | 是否只读事务 | ### 三、事务执行细节 1. **事务传播机制** 当方法嵌套调用时,根据传播行为处理事务: ```java @Transactional(propagation = Propagation.REQUIRED) // 默认 public void methodA() { methodB(); // 加入当前事务 } @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB() { // 挂起当前事务,开启新事务 } ``` 2. **回滚规则** - 默认只回滚**非检查型异常**(RuntimeException和Error) - 可通过`rollbackFor`自定义: ```java @Transactional(rollbackFor = {SQLException.class, IOException.class}) ``` 3. **事务同步机制** 通过`TransactionSynchronizationManager`绑定资源(如数据库连接)到当前线程,确保同一事务内使用相同连接。 ### 四、重要约束条件 1. **方法可见性要求** 注解必须应用于**public方法**(非public方法事务失效)[^3] ```java // 有效 @Transactional public void validMethod() {...} // 无效(不会报错但事务不生效) @Transactional private void invalidMethod() {...} ``` 2. **自调用问题** 同类中非事务方法调用事务方法会绕过代理: ```java public void outerMethod() { innerMethod(); // 事务失效! } @Transactional public void innerMethod() {...} ``` 解决方案:通过AOP上下文获取代理对象调用。 ### 五、Spring Boot自动配置 通过`@EnableTransactionManagement`开启注解驱动: 1. 自动注册`ProxyTransactionManagementConfiguration` 2. 扫描`@Transactional`注解 3. 根据数据源类型自动配置事务管理器[^4] --- **相关问题** 1. **Spring事务的传播行为有哪些具体区别?如何选择?** (深入解析`REQUIRED`、`REQUIRES_NEW`、`NESTED`等传播行为的应用场景) 2. **事务失效的常见场景有哪些?如何排查?** (分析自调用、异常捕获、方法可见性等典型陷阱的解决方案) 3. **如何在分布式系统中实现跨服务事务?** (对比JTA、Seata、Saga等分布式事务方案的整合) 4. **事务隔离级别与数据库锁机制有何关联?** (探讨读提交、可重复读等隔离级别在MySQL/Oracle中的具体实现差异) 5. **如何监控和优化Spring事务性能?** (介绍事务超时配置、只读事务提升性能、事务日志分析等实践)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值