查询、分页、排序
查询
查询有
JpaJpaRepository提供了如下表所述的内置查询。
List<T> findAll();
- 返回所有实体
List<T> findAllById(Iterable<ID> var1);
- 返回指定id的所有实体
T getOne(ID var1);
- 根据id返回对应的实体,如果未找到,则返回空。
List<T> findAll(Sort var1);
- 返回所有实体,按照指定顺序返回。
Page<T> findAll(Pageable var1);
- 返回实体列表,实体的offset 和limit通过pageable来指定
方法名字方式查询方式
Spring Data 通过查询的方法名和参数名来自动构造一个JPA QQL查询
比如
Copy public interface UserRepository extends JpaRepository < User , Integer > {
public User findByName ( String name);
}
方法名和参数名要遵守一定的规则, Spring Data JPA 才能自动转换为JPQL:
方法名通常包含多个实体属性用于查询,属性之间可以使用AND和OR连接,也支持Between、LessThan、GreaterThan、Like;
方法名可以以findBy、getBy、queryBy 开头;
查询结果可以排序,方法名包含OrderBy+属性+ASC(DESC);
一些特殊的参数可以出现在参数列表里,比如Pageeable、Sort
例子:
Copy // 根据名字查询,且按照名字升序
List< Person > findByLastnameOrderByFirstnameAsc( String name) ;
// 根据名字查询,且使用翻页查询
Page< User > findByLastname( String lastname , Pageable pageable) ;
// 查询满足条件的前10个用户
List< User > findFirst10ByLastname( String lastname , Sort sort) ;
// 使用And联合查询
List< Person > findByFirstnameAndLastname( String firstname , String lastname) ;
// 使用Or查询
List< Person > findDistinctPeopleByLastnameOrFirstname( String lastname , String firstname) ;
// 使用like查询,name 必须包含like中的%或者?
public User findByNameLike( String name) ;
findByLastnameAndFirstname
… where x.lastname = ?1 and x.firstname = ?2
findByLastnameOrFirstname
… where x.lastname = ?1 or x.firstname = ?2
findByFirstname,findByFirstnameIs,findByFirstnameEquals
… where x.startDate between 1? and ?2
findByAgeGreaterThanEqual
… where x.firstname like ?1
… where x.firstname not like ?1
findByFirstnameStartingWith
… where x.firstname like ?1
(parameter bound with appended %
)
findByFirstnameEndingWith
… where x.firstname like ?1
(parameter bound with prepended %
)
findByFirstnameContaining
… where x.firstname like ?1
(parameter bound wrapped in %
)
findByAgeOrderByLastnameDesc
… where x.age = ?1 order by x.lastname desc
findByAgeIn(Collection<Age> ages)
findByAgeNotIn(Collection<Age> age)
findByFirstnameIgnoreCase
… where UPPER(x.firstame) = UPPER(?1)
注意:Spring Data的Query 适用于关系数据库操作,也适合NOSQL。大部分Spring Boot应用中,Query构造只能创建一些简单的查询。但对于NOSQL来说已经足够了,不需要自己再构造NOSQL查询
@Query注解方式查询
注解Query允许在方法上使用JPQL
其中操作针对的是对象名和对象属性名,而非数据库中的表名和字段名
Copy @ Query ( "select u form User u where u.name=?1 and u.depantment.id=?2" );
public User findUser( String name , Integer departmentId) ;
Copy @ Query ( "form User u where u.name=?1 and u.depantment.id=?2" );
public User findUser( String name , Integer departmentId) ;
如果使用SQL而不是JPSQL,可以使用nativeQuery
属性,设置为true
Copy @ Query (value = "select * from user where name=?1 and department_id=?2" , nativeQuery = true )
public User nativeQuery( String name , Integer departmentId) ;
无论JPQL,还是SQL,都支持"命名参数":
Copy @ Query (value = "select * from user where name=:name and department_id=:departmentId" , nativeQuery = true )
public User nativeQuery2( String name , Integer departmentId) ;
如果SQL活着JPQL查询结果集并非Entity,可以用Object[]数组代替,比如分组统计每个部分的用户数:
Copy @ Query (value = "select department_id,count(*) from user group by department_id" , nativeQuery = true )
public List<Object [] > queryUserCount()
这条查询将返回数组,对象类型依赖于查询结果,被示例中,返回的是String和BigInteger类型
查询时可以使用Pageable和Sort来完成翻页和排序。
Copy @ Query ( "select u from User u where department.id=?1" )
public Page< User > QueryUsers( Integer departmentId , Pageable page) ;
@Query 还允许SQL更新、删除语句,此时必须搭配@Modifying使用,比如:
Copy @ Modifying
@ Query ( "update User u set u.name= ?1 where u.id= ?2" )
int updateName( String name , Integer id) ;
动态SQL方式查询
spring data jpa 利用JpaSpecificationExecutor做复杂查询
Spring data JPA中使用Specifications动态构建查询
Example方式查询
允许根据实体创建一个Example对象,Spring Data通过Example对象来构造JPQL。但是使用不灵活条件是AND,不能使用or,时间的大于小于,between等。
继承JpaRepository
Copy <S extends T > List< S > findAll( Example< S > var1) ;
<S extends T > List< S > findAll( Example< S > var1 , Sort var2) ;
Copy public List< User > getByExample( String name) {
Department dept = new Department() ;
dept . setId ( 1 );
User user = new User() ;
user . setName (name);
user . setDepartment (dept);
Example < User > example = Example . of (user);
List < User > list = userDao . findAll (example);
return list
}
以上代码首先创建了User对象,设置 查询条件,名称为参数name,部门id为1,通过Example.of
构造了此查询。
大部分查询并非完全匹配查询,ExampleMatcher 提供了更多的条件指定.比如以xxx开头的所有用户,则可以使用以下代码构造:
Copy ExampleMatcher matcher = ExampleMatcher . matching () . withMatcher ( "xxx" ,
GenericPropertyMatchers . startsWith () . ignoreCase ());
Example < User > example = Example . of (user , matcher);
资料:Spring Data JPA 实例查询
排序Sort
Sort对象用来指定排序,最简单的Sort对象构造可以传入一个属性名列表(不是数据库列名,是属性名)。默认采用升序排序。
Copy Sort sort = new Sort( "id" ) ;
//Sort sort = new Sort(Direction.DESC, "id");
return userDao . findAll (sort);
Hibernate 根据Sort构造了排序条件,Sort("id")
表示按照id采用默认 升序进行排序
其他Sort的构造方法还包括以下主要的一些:
public Sort(String... properties)
, 按照指定的属性列表升序排序。
public Sort(Sort.Direction direction, String... properties)
, 按照指定属性列表排序,排序由direction
指定,direction
是一个枚举类型,有Direction.ASC
和 Direction.DESC
public Sort(Sort.Order... orders)
, 可以通过Order静态方法来创建
public static Sort.Order asc(String property)
public static Sort.Order desc(String property)
分页Page和Pageable
Pageable 接口用于构造翻页查询,PageRequest是其实现类,可以通过提供的工厂方法创建PageRequest:
注意我这边使用的是sring boot 2.0.2 ,jpa版本是2.0.8,新版本与之前版本的操作方法有所不同。
public static PageRequest of(int page, int size)
public static PageRequest of(int page, int size, Sort sort) - 也可以在PageRequest中加入排序
public static PageRequest of(int page, int size, Direction direction, String... properties)
,或者自定义排序规则
page是从0开始,表示查询页,size指每页的期望行数。
Spring Data翻页查询总是返回Page对象,Page对象提供了以下常用的方法
int getTotalPages();
, 总的页数
long getTotalElements();
- 返回总数
List<T> getContent();
- 返回此次查询的结果集
示例:
Copy Public List< User > getAllUsers( int page , int size) {
PageRequest pageable = PageRequest . of (page , size);
Page < User > pageObject = userDao . findAll (pageable);
int totalPage = pageObject . getTotalPages ();
int count = pageObject . getTotalElements ();
return pageObject . getContent ()
}