JPA + @RefreshScope 引发的问题

Error creating bean with name ‘scopedTarget.configDictList’: Requested bean is currently in creation: Is there an unresolvable circular reference?

先说明下公司使用的场景:
字典表ConfigDict
所有对象都使用了监听@PreUpdate @PrePersist 事件。(对ConfigDict 的修改会进入)。

为了使用方便,将字典交给了Spring管理。

    @Bean(name = "configDictList")
    @RefreshScope
    public List<ConfigDict> list(){
        return configDictRepository.findAll();
    }

这里的@RefreshScope 是为了修改或者新增字典后会刷新bean。问题也正是加了动态刷新引起的

Listener代码:

    @PreUpdate
    @PrePersist
    void updateEnum(Object entity) {
        LOGGER.debug("进入EnumFieldListener.class");
        List<ConfigDict> list = (List<ConfigDict>) SpringContextHolder.getBean("configDictList"); // ①

}

看看修改字典的代码:

    public Resp saveOrUpdate(@Validated @RequestBody ConfigDict configDict) {
        configDictRepository.save(configDict); //②
        refreshScope.refresh("configDictList"); // ③
        return Resp.success(configDict);
    }

问题场景:
更新一次字典后,下一个更新接口更新实体A,进入了监听器,并且尝试从容器中获取字典
SpringContextHolder.getBean("configDictList") 这句代码将执行错误。

分析:
在③执行完后,将会把bean的缓存清空,代理对象还在,将会在下一次获取bean的实际去获取。
https://blog.csdn.net/tanhongwei1994/article/details/120147010

所以在执行②的时候会执行到configDictRepository.findAll() 去获取。

通过debug 这步执行过程中 又会到updateEnum方法中去。然后又获取这个bean,但是这个bean是在创建过程中了,导致了循环依赖

理论上是不应该再次进入updateEnum方法的。经过debug发现。

hibernate在执行完list方法获取后,会刷新当前会话,导致我们第二次进入更新实体A。
在这里插入图片描述

解决办法: configDictRepository.findAll() 不跟其他语句在一个会话,单独加个新事物的注解即可解决问题。

    @Bean(name = "configDictList")
    @RefreshScope
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public List<ConfigDict> list(){
        return configDictRepository.findAll();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值