spring data jpa复杂多条件查询

一.排序与分页

// 排序
Direction direction = Direction.DESC;
//directionStr为前端传值,asc代表正序
if ("asc".equals(directionStr)) {
	direction = Direction.ASC;
}
//默认使用datetime字段进行排序
String sortProperty = "datetime";
//sortParam为前端传的排序字段
if (UtilValidate.isNotEmpty(sortParam)) {
	sortProperty = sortParam;
}
Sort sort = new Sort(direction, sortProperty);

// 分页
// pageNumParam为页码,默认为0,pageSizeParam为每页条数
Pageable pageable = PageRequest.of(pageNumParam, pageSizeParam, sort);

注意:

如果想要按照外键关联实体的某个属性进行排序,sortProperty直接改为对应的 “实体名.属性名” 即可:

1.比如一个User实体对象,外键一对一关联地址实体对象Address,如果希望可以通过地址对象的id字段排序,那么sortProperty就应该传 “address.id” 。

@Entity
@Table(name="t_user")
public class User{
	@Id
	private Long id;

	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name = "address_id")
	@NotFound(action=NotFoundAction.IGNORE)
	private Address address;
	
	/**
	 * 登录名
	 */
	@Column
	private String username;

	/**
	 * 状态
	 */
	@Column
	private Integer state;

	/**
	 * 所属机构
	 */
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name = "department_id")
	@NotFound(action=NotFoundAction.IGNORE)
	private Department department;

	/**
	 * 注册时间
	 */
	@Column
	private Long datetime;
}

2.项目使用的是oracle数据库,使用这种写法刚开始一直报错,排查后发现是配置的oracle方言的问题,如果有同样使用oracle数据库的小伙伴需要注意下,以下是修改的相关配置项:

#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle9Dialect

二.复杂查询

以下的复杂查询包含了4种类型:

1.外键关联查询 — 标注1

2.或查询 — 标注2

3.外键in查询 — 标注3

4.id的in查询 — 标注4

使用JPA进行复杂多条件查询,一般都需要重写JpaSpecificationExecutor接口中的方法:

public interface JpaSpecificationExecutor<T> {

    T findOne(Specification<T> spec);

    List<T> findAll(Specification<T> spec);

    Page<T> findAll(Specification<T> spec, Pageable pageable);

    List<T> findAll(Specification<T> spec, Sort sort);

    long count(Specification<T> spec);
}

我们此处需要使用的是Page findAll(Specification spec, Pageable pageable)方法,所以要针对它进行重写:

// 假设此处查询的是用户列表
return userRepository.findAll(new Specification() {
	@Override
	public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
		List<Predicate> pList = new ArrayList<Predicate>();
		Predicate[] ps = new Predicate[pList.size()];
		List<Predicate> stateList = new ArrayList<Predicate>();
		Predicate[] statePs = new Predicate[stateList.size()];
		
		// 查询用户表中未删除的地址 (标注1)
		// 假设address是用户表User中的外键关联,存放地址信息,state为0代表有效
		pList.add(cb.equal(root.join("address").get("state"), 0));
		
		//查询状态为10-未审核或0-已审核状态的用户 (标注2)
		stateList.add(cb.equal(root.get("state"), 0));
		stateList.add(cb.equal(root.get("state"),10));
		pList.add(cb.or(stateList.toArray(statePs)));
		
		// 时间查询
		pList.add(cb.between(root.get("datetime"), start, end));
				
		// 机构查询 (标注3)
		if (UtilValidate.isNotEmpty(departsStr)) {
			Predicate pDepart = inQuery(departsStr, "department", cb, root);
			pList.add(pDepart);
		}
			
		query.where(pList.toArray(ps));
		return null;
	}
}, pageable);

以下为使用到的外键关联in查询的方法:

public Predicate inQuery(String entityIds, String entityName, CriteriaBuilder cb, Root root) {
	List<Predicate> list = new ArrayList<>();
	String[] ids = entityIds.split(",");
	if (ids != null && ids.length > 0) {
		In<Object> in = cb.in(root.join(entityName).get("id"));
		for (String id : ids) {
			Long idNum = Long.parseLong(id);
			in.value(idNum);
		}
		list.add(in);
	}

	Predicate[] p = new Predicate[list.size()];
	return cb.and(list.toArray(p));
}

如果希望进行id的in查询,只需把root.join(entityName).get(“id”)改为root.get(“id”)即可(标注4)。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盛夏温暖流年

可以赏个鸡腿吃嘛~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值