使用Spring Data Jpa接口中定义的方法查询
继承JpaRepository<T, ID>
后的方法列表
其中的大部分已经在上文一一使用,以下只使用之前未被使用的方法。
根据id
倒序查询所有用户
@Test
public void test5() {
// 方式一:使用类型安全的API定义排序表达式
Sort sort = Sort.sort(User.class).by(User::getId).descending();
// 方式二:定义排序表达式
// Sort sort = Sort.by("id").descending(); // 根据id倒序
List<User> users = userDao.findAll(sort);
for (User user : users) {
System.out.println(user);
}
}
分页查询
@Test
public void test6() {
// 同时还能指定第三参数Sort排序
// 参数:当前页码,每页条数,排序方式(可选)
PageRequest page = PageRequest.of(1,2);
Page<User> userPage = userDao.findAll(page);
System.out.println("总条数="+userPage.getTotalElements());
System.out.println("总页数="+userPage.getTotalPages());
System.out.println("当前页码(从0开始)="+userPage.getNumber());
System.out.println("每页实际条数="+userPage.getNumberOfElements());
System.out.println("每页条数="+userPage.getSize());
List<User> users = userPage.getContent();
for (User user : users) {
System.out.println(user);
}
// Hibernate: select user0_.id as id1_0_, user0_.sys_money as sys_mone2_0_, user0_.sys_password as sys_pass3_0_, user0_.sys_username as sys_user4_0_ from sys_user user0_ limit ?, ?
// 总条数=3
// 总页数=2
// 当前页码(从0开始)=1
// 每页实际条数=1
// 每页条数=2
// User(id=4, username=呵呵, password=123, money=0)
}
使用Example<S>
构造条件查询
该方式只能简单的查询,复杂查询看得看JpaSpecificationExecutor
根据用户名精确查询
@Test
public void test7() {
// 根据用户名精确查询
User user = new User();
user.setUsername("张三");
Example<User> example = Example.of(user);
List<User> users = userDao.findAll(example);
for (User u : users) {
System.out.println(u);
}
}
User中的属性必须全部为包装类,否则默认不为Null,会被添加到查询条件中。
查询用户名为张开头的用户
@Test
public void test8() {
// 查询用户名为张开头的用户
User user = new User();
user.setUsername("张");
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("username",GenericPropertyMatchers.startsWith());
// .withMatcher() 还可以添加多个条件
Example<User> example = Example.of(user,matcher);
List<User> users = userDao.findAll(example);
for (User u : users) {
System.out.println(u);
}
}
细节:
ExampleMatcher.matching()
:默认是返回满足全部条件的用户ExampleMatcher.matchingAny()
:只要有一个条件满足即可GenericPropertyMatchers.startsWith()
: 匹配开头 等价于 like 张%GenericPropertyMatchers.contains()
: 匹配中间 等价于 like %张%GenericPropertyMatchers.endsWith()
: 匹配结尾 等价于 like %张GenericPropertyMatchers.ignoreCase(boolean b)
: 同时还能指定是否忽略大小写
继承JpaSpecificationExecutor<T>
后的方法列表
查询用户名为张三的用户信息
@Test
public void test9() {
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
// 获取比较的属性
Path<Object> username = root.get("username");
// 构造查询条件
Predicate predicate = criteriaBuilder.equal(username, "张三");
return predicate;
}
};
List<User> users = userDao.findAll(specification);
users.forEach(user-> System.out.println(user));
}
root
: 查询的根对象(查询的任何属性都可以从根对象中获取)criteriaQuery
:顶层查询对象,自定义查询方式(了解:一般不用)criteriaBuilder
:查询的构造器,封装了很多的查询条件
根据用户名和密码查询用户信息
@Test
public void test10() {
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
// 获取比较的属性
Path<Object> username = root.get("username");
Path<Object> password = root.get("password");
// 构造查询条件
Predicate p1 = criteriaBuilder.equal(username, "张三");
Predicate p2 = criteriaBuilder.equal(password, "222");
// 把条件组合到一起
return criteriaBuilder.and(p1,p2);
}
};
List<User> users = userDao.findAll(specification);
users.forEach(System.out::println);
}
根据用户名模糊查询
@Test
public void test11() {
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
// 获取比较的属性,并指定比较参数的类型String
Path<String> username = root.get("username");
// 构造查询条件
Predicate p1 = criteriaBuilder.like(username, "张%");
// 把条件组合到一起
return p1;
}
};
// 根据id倒序排序
Sort sort = Sort.by("id").descending();
List<User> users = userDao.findAll(specification,sort);
users.forEach(System.out::println);
}
使用JPQL的方式查询
使用Spring Data JPA提供的查询方法已经可以解决大部分的应用场景,但是对于某些业务来说,我们还需要灵活的构造查询条件,这时就可以使用@Query
注解,结合JPQL的语句方式完成查询
@Query
注解的使用非常简单,只需在方法上面标注该注解,同时提供一个JPQL查询语句即可
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
/*
* 使用jpql语句,根据用户名查询用户信息
* 使用占位符形式,从1开始取,1说明是取方法的第一个参数
* */
@Query("from User where username=?1")
User findJpql1(String username);
/*
* 使用jpql语句,根据用户名和密码查询用户信息
* 使用命名参数,必须在参数前使用@Param来绑定参数
* */
@Query("from User where username=:uname and password=:pwd")
User findJpql2(@Param("uname") String username,@Param("pwd") String password);
}
此外,也可以通过使用 @Query 来执行一个更新删除操作,为此,我们需要在使用 @Query 的同时,用 @Modifying 来将该操作标识为修改查询
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
/*
* 使用jpql语句 完成更新、删除操作时
* - 需要手动添加事务支持,否则会报错
* 根据id修改用户名
* */
@Modifying
@Query("update User set username=?2 where id=?1")
void updateJpql(int id,String username);
// 根据id删除用户
@Modifying
@Query("delete User where id=?1")
void insertJpql(int id);
}
使用SQL语句查询
Spring Data JPA同样也支持sql语句的查询,如下:
/*
* 使用sql语句查询
* */
@Query(value = "select * from sys_user",nativeQuery = true)
List<User> findSql();
只要在@Query()
添加一个配置nativeQuery=true
即可,说明此时使用的是本地查询语句而不是jpql语句。
方法命名规则查询
顾名思义,方法命名规则查询就是根据方法的名字,就能创建查询。只需要按照Spring Data JPA提供的方法命名规则定义方法的名称,就可以完成查询工作。Spring Data JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询
按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
/*
* 使用方法名规则查询: 是spring data jpa对jpql语句更进一步的封装
* 根据用户名查询用户信息
* */
User findByUsername(String username);
}