spring data jpa 关于 List<Map>接收出现indexOut解决

懵懂的女人 提交于 2020-04-09 18:09:52

初始化过程:

    springboot自动找到继承了repository的类,为他们进行实例化。

    spring data jpa 提供了

           SimpleJpaRespositry :实现所有默认的Repository接口,中默认的操作,如findAll,delete等

          JpaRepositoryFactoryBean:FactoryBean,顾名思义,就是将repository中的bean进行装配,然后以继承repository类的类名作为key,放入  DeafultListableBeanFactory中,在我们需要的时候,从这个bean中去对应的代理进行注入。

          JdkDynamicAopProxy:动态代理的处理类,每一个方法都会经过这个拦截,然后进行处理

    附上一张时序图: 图片来源:(http://www.luckyzz.com/java/spring-data-jpa/ )

    

 

DEBUG流程解决:

    重点在于 RepositoryFactorySupport 中对我们的repository方法进行了拦截处理,执行excute方法,execute方法有两个实现类,KeyValuePartTreeQuery(用于常用的是实体query,如findAllByName)与AbstractJpaQuery(用于带有@Query注解),这边我们重点了解AbstractJpaQuery

  •                                                       
    •                                                                                             AbstractJpaQuery          

AbstractJpaQuery 调用 了JpaQueryExecution来实现execute方法,execution中 有多个语句执行器,看对应的返回值,选择不同的执行器,常用的就是collectionExecution,和pageExecution.

                                                        

                                         

                      

                                      

                      

从上面的图中,我们可以看到,jpa其实也是拦截器和反射的方法,对query中进行重新的赋值,然后进行语句的执行。

spring data jpa 提供了多个query的实现  (来源于 https://www.jianshu.com/p/fafd058911ca?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    

  • SimpleJpaQuery 适用方法:使用@Query注解,但nativeQuery为隐式或显示声明为false,即使用JPQL语法解析。
  • NativeJpaQuery 适用方法:使用@Query注解,且nativeQuery显示声明为true,即使用原生sql语法解析。
  • NamedQuery 适用方法:在entity上声明@NamedQuery注解,并在repository中使用该方法。
  • PartTreeJpaQuery 适用方法:未使用@Query注解的方法,即根据方法名反射entity字段获取sql。
  • StoredProcedureJpaQuery 适用方法:使用@Procedure注解的存储过程方法

下面看到的是NativeJpaQuery中createQuery的实现,可以看到就是先进行了排序语句的创建,然后在进行Jpa语句的创建。

                      

                          

重点来了,为什么我们在平常的编写中,有时候List<map>能够接受返回值,有时候必须要List<object[]>才能够接收呢,原因在于上面红色标注的地方,JPA在装配Bean的时候,会调用构造方法,在构造方法中,会对@query上的注解进行预处理,然后进行返回类型变量的存储,(存储在returnType中),在上面的红色圈内,进行了执行语句的判断,如下图所示。

                             

                                                                

                                       

                               

                                                       

                    

    上面几个图,可以看到的就是我们进行了一堆正则的判断,那到底是干嘛用的,其实就只是判断这个执行的语句是否有别名和默认的映射,如果存在别名和默认的映射,且相同,那么我们设置的returnType就直接返回result了,没有返回Tuple.class的类型,导致在装配返回值的时候,出现了nameIndexOut的报错,因为我们的字段名称name 为empty。

        综上所述:

            我们根据正则表达式,我们要让上面的getProjection()与alias不相等,所以正则需要匹配到,从正则表达式可以看到,getProjection()用的正则匹配没有支持大写,所以我们一般的@query中的sql语句,select 与 from 最好写成小写,然后最好出现"\n"的换行符。

    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!