实现复杂查询,使用Repository,需要实现JpaSpecificationExecutor接口
public interface UserDao extends JpaRepository,JpaSpecificationExecutor {
}
userDao.findAll(new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { }
});
Root:查询结果的一个实体对象,也就是查询结果返回的主要对象
CriteriaQuery(javax.persistence.criteria.CriteriaQuery
这个是JPA标准,用于构建查询条件,里面的方法为各种查询方式,如:distinct、select、where、groupby、having、orderby等
CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder):
用来进行函数操作,此接口很多都是返回Predicate接口的,其中包含:between(范围之间)、gt(大于),lt(小于),not(非)等操作.
JPA标准中Hibernate的两个实现方法:
1.and(org.hibernate.ejb.criteria.CriteriaBuilderImpl.and(Predicate...)) :将各个条件作为and来拼接,进行查询;
2.or (org.hibernate.ejb.criteria.CriteriaBuilderImpl.or(Predicate...)):将各条件作为or来拼接,进行查询。
这两个方法都有一个关键的接口:Predicate(javax.persistence.criteria.Predicate);是Expression(javax.persistence.criteria.Expression
1.定义一个Predicate数组,和一个临时Predicate数组,
List predicates = new ArrayList<>();
List temp = new ArrayList<>();
2.将查询条件添加到临时Predicate数组当中
temp.add(criteriaBuilder.like(userName,"%"+ user.getUserName()+"%"));
temp.add(criteriaBuilder.equal(phone,user.getPhone()));
3.再将临时数组用or或者and将查询条件拼接起来放到Predicate数组当中
predicates.add(criteriaBuilder.or(temp.toArray(new Predicate[temp.size()])));
4.最后将list转为数组执行查询
query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
简单来说:
Root:查询的实体类(user实体类)
CriteriaQuery:构建查询条件,查询哪些字段,排序是什么
CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,进行函数操作;
Predicate(Expression):单独每一条查询条件的详细描述。(条件)
实体类
package com.association.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
/**
* 用户表
*/
@Entity
@Data
@Table(name="user")
public class User extends BaseEntity {
/** 用户ID */
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
private Long userId;
/** 用户名 */
private String userName;
/** 手机*/
private String phone;
/** 状态 1:停用 0:正常*/
private String status;
/** 开始时间 */
@JsonIgnore
private String beginTime;
/** 结束时间 */
@JsonIgnore
private String endTime;
}
Dao层
@Repository
public interface UserDao extends JpaRepository,JpaSpecificationExecutor {
}
Controller层
@RestController
@RequestMapping("/api/user")
public class UserController extends BaseController {
@Autowired
UserService userService;
//region 获取用户列表
/**
* 获取用户列表
*/
@GetMapping("/list")
public TableDataInfo listUser(User user)
{
startPage();
List list = userService.selectUserList(user);
//表格分页数据
return getDataTable(list);
}
//endregion
}
service层
/**
* 用户 业务层
*/
public interface UserService
{
/**
* 根据条件分页查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
public List selectUserList(User user);
/**
* 根据搜索条件查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
List findByDynamicCases(User user);
}
serviceImpl(service实现层)
/**
* 用户 业务层处理
*
* @author baozi
*/
@Service
public class UserServiceImpl implements UserService {
//日志
private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
@Autowired
private UserDao userDao;
//region 根据条件分页查询用户列表
/**
* 根据条件分页查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
public List selectUserList(User user) {
//查询条件:1.用户姓名 2.用户电话 3.用户状态 4.创建时间范围
//如果条件都为null则查询全部
if (StringUtils.isNull(user.getUserName()) && StringUtils.isNull(user.getStatus())
&& StringUtils.isNull(user.getPhone())
&& StringUtils.isEmpty(user.getBeginTime())
&& StringUtils.isEmpty(user.getEndTime())) {
return userDao.findAll();
} else {
return findByDynamicCases(user);
}
}
//endregion
//region 查询:按条件进行动态查询
/**
* 按条件进行动态查询
* 查询条件:1.用户姓名
* 2.用户手机
* 3.用户状态
* 4.用户创建时间范围
* @return
*/
public List findByDynamicCases(User user) {
return userDao.findAll(new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
Path userName = root.get("userName");
Path phone = root.get("phone");
Path status = root.get("status");
Path createTime = root.get("createTime");
List predicates = new ArrayList<>();
List temp = new ArrayList<>();
if (user.getUserName() != null) {
temp.add(criteriaBuilder.like(userName,"%"+ user.getUserName()+"%"));
}
if (user.getPhone() != null) {
temp.add(criteriaBuilder.equal(phone,user.getPhone()));
}
if (user.getStatus() != null) {
temp.add(criteriaBuilder.equal(status,user.getStatus()));
}
if (user.getBeginTime() != null
&& user.getEndTime()!= null
&&StringUtils.isNotEmpty(user.getBeginTime())
&&StringUtils.isNotEmpty(user.getEndTime())){
temp.add(criteriaBuilder.between(createTime, DateUtils.parseDate(user.getBeginTime()), DateUtils.parseDate(user.getEndTime())));
}
predicates.add(criteriaBuilder.or(temp.toArray(new Predicate[temp.size()])));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
});
}
//endregion
}
表格分页
@Data
public class TableDataInfo implements Serializable
{
private static final long serialVersionUID = 1L;
/** 总记录数 */
private long total;
/** 列表数据 */
private List> rows;
/** 消息状态码 */
private int code;
/** 消息内容 */
private int msg;
/**
* 表格数据对象
*/
public TableDataInfo()
{
}
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List> list, int total)
{
this.rows = list;
this.total = total;
}
}