这节来讲下怎么使用springDataJpa实现简单的单表动态条件查询+分页,下面以springDataJpa提供的Example来讲解单表动态条件查询+分页。源码地址:源码下载地址。java学习交流群:184998348,欢迎大家一起交流学习。
package com.thizgroup.jpa.study.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "tb_user")
@Data//使用lombok生成getter、setter
@NoArgsConstructor//生成无参构造方法
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name",columnDefinition = "varchar(64)")
private String name;
@Column(name = "mobile",columnDefinition = "varchar(64)")
private String mobile;
@Column(name = "email",columnDefinition = "varchar(64)")
private String email;
@Column(name = "age",columnDefinition = "smallint(64)")
private Integer age;
@Column(name = "birthday",columnDefinition = "timestamp")
private Date birthday;
//地址
@Column(name = "address_id",columnDefinition = "bigint(20)")
private Long addressId;
@Column(name = "create_date",columnDefinition = "timestamp")
private Date createDate;
@Column(name = "modify_date",columnDefinition = "timestamp")
private Date modifyDate;
@Builder(toBuilder = true)
public User(Long id,String name, String mobile, String email, Integer age, Date birthday,
Long addressId) {
this.id = id;
this.name = name;
this.mobile = mobile;
this.email = email;
this.age = age;
this.birthday = birthday;
this.addressId = addressId;
}
}
下面,在IUserService中添加一个查询方法,
package com.thizgroup.jpa.study.service;
import com.thizgroup.jpa.study.model.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
/**
* 用户服务
*/
public interface IUserService {
/**
* example单表动态条件分页查询
*/
Page<User> findUserListByPage(User user,Pageable pageable);
}
然后在UserServiceImpl类中实现这个方法,
package com.thizgroup.jpa.study.service.impl;
import com.thizgroup.jpa.study.dao.UserDao;
import com.thizgroup.jpa.study.dao.UserRepository;
import com.thizgroup.jpa.study.dto.AddressDTO;
import com.thizgroup.jpa.study.dto.PageRecord;
import com.thizgroup.jpa.study.dto.UserDTO;
import com.thizgroup.jpa.study.dto.UserProjection;
import com.thizgroup.jpa.study.model.User;
import com.thizgroup.jpa.study.service.IUserService;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@Service
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public class UserServiceImpl implements IUserService {
@Autowired
private UserRepository userRepository;
@Override
public Page<User> findUserListByPage(User user, Pageable pageable) {
Example<User> example = Example.of(user,
模糊查询匹配开头,即{name}%
ExampleMatcher.matching().withMatcher("name",ExampleMatcher.GenericPropertyMatchers.startsWith())
//是否包含某个字符串 email like ‘%’ + ?0 + ‘%’
.withMatcher("email",ExampleMatcher.GenericPropertyMatchers.contains())
//按照年龄精确查询
.withMatcher("age",ExampleMatcher.GenericPropertyMatchers.exact()));
return userRepository.findAll(example,pageable);
}
}
此外,ExampleMatcher.GenericPropertyMatcher还提供了其他的查询条件,整理如下:
方法 | 描述 |
---|---|
ignoreCase | 忽略大小写 |
caseSensitive | 大小写敏感 |
endsWith | 以什么结尾 |
exact | 精确查询 |
contains | 是否包含某个字符串 |
startsWith | 以什么开始 |
不幸的是,即使开发人员最初认为支持正则表达式(因为存在上述枚举常量),Spring实际上目前不支持它们——并且根据相关JILA问题的讨论,它永远不会:HTTPS://JIRA.SpRIP.IO/BROSESE/DATAJPA-944
下面写个单元测试验证上面的代码:
package com.thizgroup.jpa.study.service;
import com.thizgroup.jpa.study.JpaApplication;
import com.thizgroup.jpa.study.model.User;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest(classes={JpaApplication.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public class UserServiceImplTest {
@Autowired
private IUserService userService;
@Test
public void findUserListByPage3Test() throws Exception{
User u = new User();
u.setName("张");
u.setEmail("@qq.com");
u.setAge(35);
//注意:jpa的分页是从0开始的
Page<User> pageList = userService.findUserListByPage(u, PageRequest.of(0, 15));
System.out.println("分页信息:");
System.out.println("总记录数:"+pageList.getTotalElements()+",总页数:"+pageList.getTotalPages());
System.out.println("页码:"+(pageList.getNumber()+1)+",每页条数:"+pageList.getSize());
List<User> content = pageList.getContent();
content = null == content? new ArrayList<>() : content;
content.forEach(user->System.out.println(user));
}
}
运行上面的单元测试,结果如下:
分页信息:
总记录数:1,总页数:1
页码:1,每页条数:15
User(id=1, name=张三, mobile=156989989, email=hu@qq.com, age=35, birthday=2008-09-16 08:00:00.0, addressId=11, createDate=2019-08-06 05:50:01.0, modifyDate=2019-08-08 05:46:11.0)
如果需要详细了解Example查询,推荐这篇文章:Spring Data JPA 实例查询.
至此,springDataJpa Example单表动态条件查询+分页就介绍完了,有需要源码的朋友,请到git上下载源码,源码地址:https://github.com/hgq0916/springdatajpa-study.git。java学习交流群:184998348,欢迎大家一起交流学习。