jpa在save失败后service端catch不到异常原因(Hibernate的一级缓存)

75 篇文章 5 订阅
5 篇文章 0 订阅

现象

jpasave失败后servicecatch不到异常原因。

jpasave是先保存到缓存的,没有立即插入到数据库,在提交事务时,才会尝试刷新缓存中的数据到数据库。

或者手动调用flush方法,强制把数据刷到数据库。

Hibernate缓存包括两大类:一级缓存和二级缓存。

一级缓存又称为“Session的缓存”,它是内置的,不能被卸载(不能被卸载的意思就是这种缓存不具有可选性,必须有的功能,不可以取消session缓存)。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存在第一级缓存中,持久化类的每个实例都具有唯一的OID。我们使用@Transactional 注解时,JpaTransactionManager会在开启事务前打开一个session,将事务绑定在这个session上,事务结束session关闭,所以后续内容将以粗略以事务作为一级缓存的生存时段。

二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件,二级缓存应用场景局限性比较大,适用于数据要求的实时性和准确性不高、变动很少的情况。

一般不会开启二级缓存,会引入诸如并发方面的问题

save方法流程

我们使用CrudRepository.save方法保存或更新对象的流程如下:

在这里插入图片描述

其中如果entity实体设置了自增主键,就只会打印出一条insert语句.即直接插入。

而如果entity只是设置了主键,未设置增长策略,在调用save方法时,就会先打出一条select语句,再打出一条insert语句。如果加了事务,调用save方法时,会出现save失败后servicecatch不到异常的现象,因为先保存到了一级缓存,等这个方法结束后提交事务才会将数据刷到数据库,这个时候数据库那边报错了,这个异常就会返回到调用这个方法的层级。

综上分析
如果实体类使用自增主键,无论是否加事务,都先将缓存中的数据插入数据库,再执行业务操作,可以正常触发try-catch的异常捕获。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

不设置主键的自增策略,加事务,会先将数据保存在缓存,然后执行余下的业务逻辑,然后再将缓存中的数据刷新到数据库中,在刷数据到库时发生异常,但由于此时业务逻辑已经执行完,无法触发try-catch的异常捕获机制。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值