# spring-data-jpa-condition **Repository Path**: lzc08/spring-data-jpa-condition ## Basic Information - **Project Name**: spring-data-jpa-condition - **Description**: JPA封装 - **Primary Language**: Java - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2017-11-14 - **Last Updated**: 2025-03-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring Data JPA Condition Spring Data JPA 动态查询工具类,用于快速生成动态查询的查询条件 ## Features ## * 快速生成Predicate条件 * 极简代码,良好可读性 * 基于实体类的属性进行自动遍历,自动处理空属性 * 支持自定义扩展 ## Getting Help ## ## Quick Start ## Download the jar through Maven: ```xml org.springframework.data spring-data-jpa-condition 1.0-SNAPSHOT ``` #### 相关API #### ```java JpaSpecificationExecutor.findOne(Specification spec); Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb); ``` #### 前置条件 #### ```java public interface YourRepository extends JpaRepository, JpaSpecificationExecutor ``` #### Example #### ```java // Test Entity // 用于演示的实体类 public class YourEntity { private Long id; private String category; private String desc; private String code; private Integer value; private Date date; // Use To Between @Transient private Date dateStart; @Transient private Date dateEnd; } ``` Use JPA Condition ```java // 使用 JPA Condition,极简的代码,并保持良好的可读性 Specification specification = JpaConditionUtils.specification(yourEntity, (root, query, cb, jc) -> { // where category = :category jc.clauseAnd(jc.equal("category")) // and desc = :desc or code = :code or value = :value .clauseAnd(jc.orEqualInclude("desc", "code", "value")); }); YourEntity one = yourRepository.findOne(specification); // Also you can use Native API like this // 同时也支持 Spring Data JPA 原生API jc.clauseAnd(cb.equal(root.get("id"), yourEntity.getId())); // Example Between jc.clauseAnd(jc.between("date")); ``` Use Spring Data JPA ```java // 使用 Spring Data JPA,冗长的代码,无法保持良好的可读性 Specification specification = (root, query, cb) -> { // 1. category = :category Predicate category = cb.equal(root.get("category"), yourEntity.getId()); // 2. desc = :desc Predicate desc = cb.equal(root.get("desc"), yourEntity.getDesc()); // 3. code = :code Predicate code = cb.equal(root.get("code"), yourEntity.getCode()); // 4. value = :value Predicate value = cb.equal(root.get("value"), yourEntity.getValue()); // 5. (2 or 3 or 4) Predicate or = cb.or(desc, code, value); // use mergeOr() of JPA Condition // where 1 and 5 return cb.and(category, or); // use clauseAnd() of JPA Condition }; YourEntity one = yourRepository.findOne(specification); ``` ### merge & clause ### 在JPA Condition中,and/or被拆分成两种类型的操作,以明确它们的语义 #### merge #### > mergeAnd & mergeOr merge操作仅合并查询条件,而不会将查询条件注入到CriteriaQuery #### clause #### > clauseAnd & clauseOr clause操作合并条件,并将查询条件注入到CriteriaQuery ### JPA Condition API ### ```java /** * Equal条件 * * @return List * @apiNote range:Entity.attributes */ public Predicate[] equals(); /** * Equal条件 * * @param names 属性名数组 * @return Predicate * @apiNote range:Entity.attributes in names */ public Predicate[] equalsInclude(@NotNull String... names); /** * Equal条件 * * @param names 属性名数组 * @return Predicate * @apiNote range:Entity.attributes not in names */ public Predicate[] equalsExclude(@NotNull String... names); /** * Like条件 * * @return Predicate */ public Predicate[] likes(); public Predicate[] likesInclude(@NotNull String... names); public Predicate[] likesExclude(@NotNull String... names); /** * Between条件 * * @param name 属性名, Entity中必须有[name+"Start"]和[name+"End"]属性 * @return Predicate * @apiNote startValue <= root.get(name) < endValue */ public > Predicate between(String name); /** * Between条件 * * @param ignoreNull 忽略空值 * @param name 属性名, Entity中必须有[name+"Start"]和[name+"End"]属性 * @return Predicate * @apiNote startValue <= root.get(name) < endValue */ public > Predicate between(boolean ignoreNull, String name); /** * Between条件 * * @param ignoreNull 忽略空值 * @param name 属性名 * @param startValue 起始值 * @param endValue 结束值 * @param 值类型 * @return Predicate * @apiNote startValue <= root.get(name) < endValue */ public > Predicate between(boolean ignoreNull, String name, T startValue, T endValue); /** * OrEqual条件 * * @param names 属性名数组 * @return Predicate * @apiNote range:Entity.attributes in names * @apiNote builder.or(equalsInclude(names)) */ public Predicate orEqualInclude(@NotNull String... names); ``` ## Core ## ### JpaConditionUtils ### ```java /** * 生成JPA查询明细 * * @param model 实体类 * @param specification ConditionSpecification * @param 实体类类型 * @return Specification */ @SuppressWarnings("unchecked") public static Specification specification(T model, ConditionSpecification specification) /** * 实例化Jpa条件查询 * * @param root * @param query * @param cb * @param model 实体类 * @param 实体类类型 * @return JpaCondition */ public static JpaCondition condition(Root root, CriteriaQuery query, CriteriaBuilder cb, T model) ``` ### JpaCondition ### ### ConditionSpecification ###