查询、分页、排序
查询、分页、排序
查询
查询有
方法名字方式查询
@Query注解方式查询
动态SQL方式查询
Example方式查询
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查询
比如
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);
可以通过Top、First来限定查询的结果集;
一些特殊的参数可以出现在参数列表里,比如Pageeable、Sort
例子:
// 根据名字查询,且按照名字升序
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);
Keyword
Sample
JPQL snippet
And
findByLastnameAndFirstname
… where x.lastname = ?1 and x.firstname = ?2
Or
findByLastnameOrFirstname
… where x.lastname = ?1 or x.firstname = ?2
Is,Equals
findByFirstname,findByFirstnameIs,findByFirstnameEquals
… where x.firstname = 1?
Between
findByStartDateBetween
… where x.startDate between 1? and ?2
LessThan
findByAgeLessThan
… where x.age < ?1
LessThanEqual
findByAgeLessThanEqual
… where x.age <= ?1
GreaterThan
findByAgeGreaterThan
… where x.age > ?1
GreaterThanEqual
findByAgeGreaterThanEqual
… where x.age >= ?1
After
findByStartDateAfter
… where x.startDate > ?1
Before
findByStartDateBefore
… where x.startDate < ?1
IsNull
findByAgeIsNull
… where x.age is null
IsNotNull,NotNull
findByAge(Is)NotNull
… where x.age not null
Like
findByFirstnameLike
… where x.firstname like ?1
NotLike
findByFirstnameNotLike
… where x.firstname not like ?1
StartingWith
findByFirstnameStartingWith
… where x.firstname like ?1
(parameter bound with appended %
)
EndingWith
findByFirstnameEndingWith
… where x.firstname like ?1
(parameter bound with prepended %
)
Containing
findByFirstnameContaining
… where x.firstname like ?1
(parameter bound wrapped in %
)
OrderBy
findByAgeOrderByLastnameDesc
… where x.age = ?1 order by x.lastname desc
Not
findByLastnameNot
… where x.lastname <> ?1
In
findByAgeIn(Collection<Age> ages)
… where x.age in ?1
NotIn
findByAgeNotIn(Collection<Age> age)
… where x.age not in ?1
True
findByActiveTrue()
… where x.active = true
False
findByActiveFalse()
… where x.active = false
IgnoreCase
findByFirstnameIgnoreCase
… where UPPER(x.firstame) = UPPER(?1)
注意:Spring Data的Query 适用于关系数据库操作,也适合NOSQL。大部分Spring Boot应用中,Query构造只能创建一些简单的查询。但对于NOSQL来说已经足够了,不需要自己再构造NOSQL查询
@Query注解方式查询
注解Query允许在方法上使用JPQL
其中操作针对的是对象名和对象属性名,而非数据库中的表名和字段名
@Query("select u form User u where u.name=?1 and u.depantment.id=?2");
public User findUser(String name, Integer departmentId);
@Query("form User u where u.name=?1 and u.depantment.id=?2");
public User findUser(String name, Integer departmentId);
如果使用SQL而不是JPSQL,可以使用nativeQuery
属性,设置为true
@Query(value="select * from user where name=?1 and department_id=?2", nativeQuery=true)
public User nativeQuery(String name, Integer departmentId);
无论JPQL,还是SQL,都支持"命名参数":
@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[]数组代替,比如分组统计每个部分的用户数:
@Query(value="select department_id,count(*) from user group by department_id", nativeQuery=true)
public List<Object[]> queryUserCount()
这条查询将返回数组,对象类型依赖于查询结果,被示例中,返回的是String和BigInteger类型
查询时可以使用Pageable和Sort来完成翻页和排序。
@Query("select u from User u where department.id=?1")
public Page<User> QueryUsers(Integer departmentId, Pageable page);
@Query 还允许SQL更新、删除语句,此时必须搭配@Modifying使用,比如:
@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
<S extends T> List<S> findAll(Example<S> var1); <S extends T> List<S> findAll(Example<S> var1, Sort var2);
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开头的所有用户,则可以使用以下代码构造:
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("xxx",
GenericPropertyMatchers.startsWith().ignoreCase());
Example<User> example = Example.of(user, matcher);
排序Sort
Sort对象用来指定排序,最简单的Sort对象构造可以传入一个属性名列表(不是数据库列名,是属性名)。默认采用升序排序。
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
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();
- 返回此次查询的结果集
示例:
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()
}
Last updated
Was this helpful?