SpringBoot之Jpa查询

标签: Springboot 分类: Java 创建时间:2020-08-13 06:54:49 更新时间:2023-10-20 11:23:26

1.in查询

使用SpringBoot Jpa进行in查询,有两种方式,一种就是使用@Query自定义查询,一种就是使用Specification定义查询语句,这种方式我就不写了,在另一篇文章(Post not found: Spring Boot之Jpa动态SQL语句 Spring Boot之Jpa动态SQL语句) 中有部分代码。

1
2
3
4
5
6
public interface SiteinfoRepo extends JpaRepository<SiteInfo,Long>, JpaSpecificationExecutor {

@Query("select s from SiteInfo s where s.SiteNo in (:siteNos)")
List<SiteInfo> findInSiteNo(@Param("siteNos")List<Integer> siteNos);

}
参考文章:
1.jpa Query查询,时间查询,in查询(Spring Data Jpa 3) (这篇文章的中部,有使用@Query定义in查询的方法)
2.@Query注解的用法(Spring Data JPA)

2.分页查询

在SQL server中没有limit方法,实现分页查询就比较麻烦,除此之外,除了要获取分页信息,还要获取数据总量,所以要进行两次查询。刚开始我想着使用一个查询,同时获取分页信息及数据总量,主要就是将数据总量作为一个列,附加在查询结果的后面返回,比如下面的代码,主要使用了 row_number() over 和 COUNT (*) OVER () AS total 两个方法,然后再将数据一一对应

1
2
3
4
@Query(value="SELECT * FROM (select row_number() over (order by RecordTime ) as ROW_COUNT , *,COUNT (*) OVER () AS total from " +
"secHis t where sectionId =?1 and (RecordTime between ?2 and ?3)) as b " +
"where ROW_COUNT between (?4-1)*?4 and ?4*?5",nativeQuery=true)
List<Object> findBySectionIdAndRecordTimeBetweenMax(Integer section, Date starttime, Date endtime,Integer pageIndex,Integer pageSize);

在参考文章中,定义了一种,使用@Query进行分页查询的方法,可以在@Query中定义一个countQuery额外的查询,就可以同时使用jpa自带的分页操作了。

1
2
3
4
5
6
7
8
9
10
// 定义分页方法
Pageable pageable = PageRequest.of(0,3, Sort.Direction.DESC,"id");

// 定义分页查询
@Query(
value = "SELECT * FROM Users ORDER BY id",
countQuery = "SELECT count(*) FROM Users",
nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);

但是这样做会执行两次查询,这个要注意。比如下面的内容,就要定义两次where才能获取正确的totalElements

1
2
3
4
5
@Query(value = "select row_number() over (order by RecordTime ) as id, * from secHis t" +
" where sectionId =:section and (RecordTime between :starttime and :endtime) order by RecordTime",
countQuery = "SELECT count(*) FROM SecHis where sectionId =:section and (RecordTime between :starttime and :endtime)",
nativeQuery = true)
Page<SecHis> findBySectionIdAndRecordTimeBetweenPage(Integer section, Date starttime, Date endtime, Pageable pageable);
参考文章:
1.Spring Data JPA @Query (这是官方的对于@Query的解释,里面涉及到了分页查询,集合查询in,索引方式查询以及命名方式查询等,仔细阅读,可以解决我以前在使用jpa的时候,出现的很多的不解)
2.Spring Data JPA实现分页Pageable的实例代码
3.hibernate分页原理
4.使用 JPQL 和原生 SQL 查询 JPA 实体
5.复杂sql——分页查询同时查出数据总量 (这篇文章中提到了COUNT (1) OVER ()这个方法)

问题

(1)’offset’ 附近有语法错误
在使用@Query进行自定义分页查询的时候,出现了这个问题。

主要原因应该时数据库方言的问题,sql server 2008版本中没有offset fetch next方法实现的分页,所以应该将hibernate方言定义为org.hibernate.dialect.SQLServer2008Dialect 而不是org.hibernate.dialect.SQLServer2012Dialect。

但是话有说回来了,使用SQLServer2008Dialect方言,会带来一个分页比较慢的问题,就像参考文章2一样,hibernate默认使用的是top方式查询的分页,而不是row_number的方式,所以会拖慢程序。

参考文章:
1.sqlsever2012使用pageHelper分页插件报错解决
2.解决hibernate对Sql Server分页慢的问题 (这里重写了hibernate的底层方言,使用了ROW_MUBBER()函数进行快速的查询)

(2) Could not locate ordinal parameter [1], expecting one of
解决了分页查询的方言问题之后,出现了无法定位参数的问题,显示这三个参数都没有找到。

最后将位置参数,改为了命名参数

1
2
3
4
5
6
7
8
9
// 正确的查询语句
@Query(value = "select row_number() over (order by RecordTime ) as id, * from secHis t" +
" where sectionId =:section and (RecordTime between :starttime and :endtime) order by RecordTime",countQuery = "SELECT count(*) FROM SecHis",nativeQuery = true)
Page<SecHis> findBySectionIdAndRecordTimeBetweenPage(Integer section, Date starttime, Date endtime, Pageable pageable);

// 错误的查询语句
@Query(value = "select row_number() over (order by RecordTime ) as id, * from secHis t" +
" where sectionId =?1 and (RecordTime between ?2 and ?3) order by RecordTime",countQuery = "SELECT count(*) FROM SecHis",nativeQuery = true)
Page<SecHis> findBySectionIdAndRecordTimeBetweenPage(Integer section, Date starttime, Date endtime, Pageable pageable);
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。