spingBoot中spring data jpa的一次查询问题解决

spingBoot中spring data jpa的一次查询问题解决

这个问题令我真的是印象深刻。现在记录一下该问题的详细解决过程,解决问题的思路很重要。

1.问题描述:

一个简单的查询,根据某字段查询值,实体类是一个视图。
dao:

    @Query(value="from ViewGxxx  where num = ?1")
    VietEntity findByunt1(String ccount);

查询:

     ViewDebtEntity en1 = viewDao.findByAccount1(dkzhList.get(1));
     ViewDebtEntity en2 = viewDao.findByAccount1(dkzhList.get(0));
    ViewDebtEntity  en3 = viewDao.findBytAccount1("021001055215000000790");

三个查询条件是不相同的。
查询结果以及现象如下:

  1. 所有的值都相同,en1 = en2 = en3
  2. 比如第一次查的结果为“xxx” , 那之后多次查询的结果都为“xxx” ,尽管查询条件都不一样。

2.问题解决

开始用的是 根据方法名查询的 如 findbyxxxIn(List) , 就是参数是一个list , 批量查询,
出现问题后,以为是方法的问题,后来就改为上述的直接用jpql 语句查询。然后问题依旧存在。

  • debug调试,查看查询方法的输入参数,确实不一样。
  • 用上述几个不同的参数去数据库写sql 查询,确实能查到不同的数据。
  • 改变日志数据,查看spring data jpa 发送的sql 打印,看到三次打印的sql , 一模一样但是参数却是个 “?” 。
  • 改变日志输出配置,让sql 的参数也显示出来。具体做法
  • sql 参数也打印了出来,结果发现,发送的sql的参数也的确是不同的。

进行到这里就真的感到这个问题妖异的很了。

接下来进行进一步分析。

什么原因能导致这样的现象呢, 想想看,同样的sql 语句,不同的参数,查询出来的结果都一样,并且都等于第一次查询的。
那就难免想到缓存的东西了,问题是这种缓存明显是不合逻辑也不合常理的。

最后去看了实例类(orm 数据里边是view)

在这里插入图片描述
注意这里将id 视为主键 (逻辑上不允许重复的)

然后去数据库一探究竟:
在这里插入图片描述

看到一个id的字段,值却都是相同的. 这…

然后带着这个证据去分析上述的问题:

  1. 我是将id属性用@Id 作为主键, 那么 sping data jpa 就认为id 属性是唯一的.
  2. 然后我进行第一次查询,得到 en1, 得到的结果为 xxx (id 为1) sping data jpa 底层实现用的hibernate 发送sql 进行查询,.
  3. 然后进行第二次查询,然后发送sql , 数据库的索引机制,查找普通字段,会先找到对应id , 然后,有id ,查询对应的整个记录. 由于 第二次查询虽然用的不同条件,但是对应的id相同,于是从缓存中返回了上次相同id的查询结果.

因此这个视图的数据是有问题的了,id 都一样, 为了证实这一点,我再视图里边找了一个唯一的字段,响应的在其上边加上@Id注解, 再进行查询得到的结果就是不同的了.

发布了132 篇原创文章 · 获赞 108 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/fanbaodan/article/details/103187101