解决:jpa中更新数据库数据后由于缓存问题导致查询出的数据不是数据库中最新数据

在某一方法中对A对象进行修改操作,且在这个方法返回之前对A对象进行查询。发现得到的数据是A对象修改之前的数据,而并非A对象修改之后的数据。这是什么原因造成的呢?
答:缓存问题。

为什么说是缓存问题呢?

都知道JPA的底层实现是Hibernate,也可以说JPA是Hibernate的升级版本。

Hibernate的缓存机制分为:一级缓存和二级缓存。

  • 一级缓存:hibernate默认开启一级缓存,仅当commit或者flush时会根据快照机制确定是否更新到数据库。(快照机制:数据操作时,不仅会把数据放入一级缓存区,还会把相同的数据放入快照区。在此期间,若数据变更,缓存区的数据也会发生变化。当commit或者flush时,会对比缓存区和快照区的数据是否一致,如果一致(数据无变化)不进行操作,若不一致(缓存区的数据发生了变化)则调用update方法,更新数据到数据库。)
  • 二级缓存:二级缓存默认是关闭的,多用于存放频繁查询,且变更机率较小的数据。相同数据查询时,直接从缓存中取,而不再访问数据库。减轻了数据库的压力。

默认查询时会先去一级缓存中取数据,取不到数据会去二级缓存中取(配置了二级缓存),如果还是没有取到数据,则访问数据库。

Repository中方法都加了事务,默认@Transactional(readOnly = true)只读。
查询操作时无影响,进行修改和删除操作时需要添加@Modifying和@Transactional
  • @Modifying标识该操作是修改操作
  • @Transactional声明事务性操作,Transactional(readOnly = false)可进行修改操作
不加@Modifying会出现以下问题:
org.hibernate.hql.QueryExecutionRequestException: Not supported for DML operations

   
   
  • 1
不加@Transactional会出现以下情况:
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

   
   
  • 1

使用时你可能会发现,对某一数据进行update操作后查询该数据,得到的是update之前的数据,而不是最新的数据。这是缓存造成的。

解决办法:设置@Modifying(clearAutomatically=true) 会刷新一级缓存,得到最新的数据。
注意:clear后会把最新的数据刷新到一级缓存中,但不会flush,如果此时调用save()方法(刷新缓存)但不会把最新数据更新到数据库,在此期间(未flush)调用@Modifying(clearAutomatically=true)方法操作的数据可能就不是正确的,因此必须使用saveAndFlush(),或者设置flushAutomatically = true

设置如下:会在执行修改操作之前flush数据,从而拿到最新的数据。

@Modifying(clearAutomatically = true, flushAutomatically = true) 

   
   
  • 1
另外一种清缓存的办法:引入EntityManager,在获取最新数据之前进行clear
 @Autowired
    private EntityManager entityManager;

   
   
  • 1
  • 2
entityManager.unwrap(Session.class).clear();

   
   
  • 1

转发:https://blog.csdn.net/weixin_43770545/article/details/103732082

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用JPA的IN查询时,如果数据量太大导致执行时间过长,你可以尝试以下几种优化方法: 1. 分批查询:将大查询分成多个较小的查询,每次查询一部分数据。你可以使用分页或者限制查询结果数量来实现。这样可以减少一次性加载大量数据的压力。 2. 批量操作:如果你需要对查询结果进行更新或者删除操作,可以考虑使用批量操作。通过批量更新或批量删除的方式,可以减少数据库交互次数,提高执行效率。 3. 使用索引:确保查询所涉及的列都被适当地索引。索引可以加快查询速度。使用合适的索引可以优化IN查询。 4. 缓存查询结果:如果查询结果是不经常变化的静态数据,可以将查询结果缓存缓存,下次查询时直接从缓存获取,而不是每次都执行数据库查询。 5. 数据库优化:可以对数据库进行性能优化操作,如增加内存、调整数据库参数等。这些优化操作可能需要DBA或数据库专家的参与。 6. 数据库分片:如果数据量非常大,可以考虑使用数据库分片技术,将数据分散存储在多个数据库节点,从而提高查询效率。 以上是一些常用的优化方法,你可以根据具体情况选择适合的方法。同时,建议使用工具进行性能分析,找具体执行过程的瓶颈,并进行有针对性的优化。 希望对你有帮助!如果还有其他问题,请继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值