SSH架构
业务原型:
在一级事务T1中查询出id为12345的持久化对象A1,并修改了A1的memo属性,T1提交之前调用了一个方法M,M中使用PROPAGATION_REQUIRES_NEW开启了一个新的事务T2,在T2中又查询出id为12345的持久化对象A2,修改了A2的memo属性,在T2提交后,A2的memo变化被同步到数据库中,但是在T1提交后A1所做的修改却没有同步到数据库中,而且也没有报数据版本异常。
通过调试发现:A1和A2虽然指向数据库中的同一行,但是是不同的对象实例
疑问:
1、Hibernate的持久化对象只应该在系统中存在一份,为什么这儿会出现A1、A2两个持久化对象呢?
2、为什么T1没有做任何提交动作(因为如果提交了的话肯定会报数据版本不同的异常)
源码分析:
在TransactionTemplate的<T> T execute(TransactionCallback<T> action)中会通过TransactionManager的getTransaction方法来取得TransactionStatus
1、取得当前线程所关联的SessionHolder
2、若存在SessionHolder并且开启了事务(this.sessionHolder != null && this.sessionHolder.getTransaction() != null),而且当前的的传播行为为PROPAGATION_REQUIRES_NEW
3、挂起当前线程绑定的事务及其事务同步器,取消当前线程和当前session和connection的绑定,并保存所有的挂起信息以供恢复
4、创建新的session,并开启新的事务
5、执行TransactionTemplate的TransactionCallback回调
6、在新事务提交后,会恢复上个事务的所有信息和执行
答1:可以看出,使用PROPAGATION_REQUIRES_NEW时,Spring会在一个请求线程中生成另一个独立的Hibernate的session和事务,所以会存在两份持久化对象
如果将事务传播方式改为PROPAGATION_NESTED,Spring会使用之前session和事务,并通过事务的SavePoint来实现嵌套事务。
另外,在Hibernate的reference里面有句话:A Hibernate Session is a transaction-level cache of persistent data. 可以理解为在一个session中只能有一个关联的事务(嵌套事务只是父事务的savepoint,不能算作一个事务),一旦这个事务结束将会移除这个关联关系(JDBCContext.afterTransactionCompletion方法中),并且一个session中开启的多个事务可以共享缓存
答2:怀疑在T1检查脏数据时认为没有脏数据,所以没有做任何提交
答2:跟踪发现确实报了乐观锁异常,日志打到另外的地方去了
分享到:
相关推荐
而PROPAGATION_REQUIRES_NEW则总是新建一个事务,即使在已有事务中调用,也会暂停当前事务,执行新的事务。 在实际开发中,我们还需要关注事务的隔离级别,包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ...
3. **事务传播行为** - `@Transactional`的propagation属性定义了事务如何在不同方法间传播,如REQUIRED(默认,如果存在事务则加入,否则新建)、REQUIRES_NEW(总是新建事务)等。 4. **事务隔离级别** - 包括...
- **PROPAGATION_REQUIRES_NEW**:新建一个事务,如果已有事务,暂停原事务。 - **PROPAGATION_NOT_SUPPORTED**:不使用事务,如果已有事务,暂停原事务。 - **PROPAGATION_NEVER**:不使用事务,如果已有事务,抛出...
4. 支持Spring的事务传播行为:如PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等,根据业务场景灵活选择事务处理方式。 在实际开发中,这两个jar包的结合使用,可以让开发者在享受Spring的便利性的同时,利用...
- `PROPAGATION_REQUIRES_NEW`:总是新建事务,如果已有事务则挂起。 - `PROPAGATION_SUPPORTS`:如果有事务则参与,无事务则非事务执行。 - `PROPAGATION_NOT_SUPPORTED`:非事务执行,如果已有事务则挂起。 - ...
- **事务传播行为**: 可以配置不同的事务传播属性,如PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等。 - **事务回调**: 可以使用@Transactional注解来声明方法需要在事务中执行。 5. **注解方式集成** - **...
4. **事务传播行为**: @Transactional注解还支持不同的事务传播行为,如PROPAGATION_REQUIRED(默认,如果当前存在事务则加入,否则新建)、PROPAGATION_REQUIRES_NEW(总是新建事务,如果存在则挂起)等。...
- 通过@Transactional注解进行事务控制,理解事务传播行为(PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等)。 25-34. **Spring与其他框架的集成** - 集成JDBC,使用Spring的JdbcTemplate简化数据库操作。 ...
- `PROPAGATION_REQUIRES_NEW`:总是新建事务。 - `PROPAGATION_NOT_SUPPORTED`:如果有事务则挂起,以非事务方式运行。 - `PROPAGATION_NEVER`:总是以非事务方式运行,如果当前存在事务则抛出异常。 - `...
REQUIRES_NEW(新建事务,无论是否存在当前事务)、PROPAGATION_NOT_SUPPORTED(不支持当前事务,以非事务方式执行)、PROPAGATION_NEVER(不允许存在当前事务,否则抛异常)和PROPAGATION_NESTED(嵌套事务)。...
在声明式事务管理中,我们还可以配置不同的事务传播行为,例如PROPAGATION_REQUIRED(默认,新事务或加入现有事务)、PROPAGATION_REQUIRES_NEW(总是开始新事务)、PROPAGATION_SUPPORTS(如果已有事务则加入,否则...
4. **PROPAGATION_REQUIRES_NEW**:新建事务,如果当前存在事务,则把当前事务挂起。 5. **PROPAGATION_NOT_SUPPORTED**:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 6. **PROPAGATION_NEVER**:以非...
Spring定义了七种事务传播行为,比如PROPAGATION_REQUIRED(默认,若无事务则新建)、PROPAGATION_SUPPORTS(若有事务则加入,否则非事务运行)、PROPAGATION_REQUIRES_NEW(总是新建事务,若已有事务则挂起)等,...
在Spring框架中,面试常涉及的关键知识点包括Spring的IoC(控制反转)、依赖注入、Bean的生命周期、AOP(面向切面编程)、事务管理、设计模式以及特定的类和注解如`@Service`、`@Repository`和`ThreadLocal`的使用。...
PROPAGATION_REQUIRES_NEW总是开启新事务,挂起现有事务等。 至于JVM内存区域,主要包括堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(PC Register)、本地方法栈(Native Method Stack)和元空间...
此外,了解Spring的事务管理策略,如PROPAGATION_REQUIRED和PROPAGATION_REQUIRES_NEW,也是十分必要的。 总之,MyBatis-Spring的出现让Spring和MyBatis的结合变得更加紧密和高效,它简化了项目结构,提高了代码的...
5. **Spring事务的传播属性和隔离级别**:传播属性包括PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等,定义了事务如何在不同方法间传播;隔离级别有READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和...
- **@Transactional**:在方法上标注,开启事务管理,支持PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等事务传播行为。 6. **Spring Data JPA与Spring Boot集成** - 在Spring Boot项目中,通过添加`spring-...
41. **Spring事务传播行为和隔离级别**:如PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等,隔离级别有READ_UNCOMMITTED等。 42. **IOC与DI**:控制反转(IOC)将对象的创建和依赖关系交给容器管理,依赖注入...