# query4jpa **Repository Path**: lisrlee/query4jpa ## Basic Information - **Project Name**: query4jpa - **Description**: query4jpa是一个基于Springboot-data-jpa实现的专注于查询的库,提供灵活的动态查询方式,解决JPA动态查询的痛点 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-12-14 - **Last Updated**: 2026-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # query4jpa [TOC] #### 介绍 query4jpa是一个基于Springboot-data-jpa实现的专注于查询的库。本库提供四种查询方式: - 基于注解的实体查询 - 基于注解的原生SQL查询 - 基于XML文件的原生SQL查询 - 基于方法的实体查询 [范例参考](https://gitee.com/lisrlee/query4jpa/tree/master/query4jpa-test) #### 使用说明 ##### 1.maven依赖 ```xml io.gitee.lisrlee query4jpa 1.0.1 ``` ##### 2.@EnableJpaQuery开启功能 ```java @SpringBootApplication @EnableJpaQuery public class TestApp { public static void main(String[] args) { SpringApplication.run(TestApp.class); } } ``` ##### 3.基于注解的实体查询 - 定义查询条件对象qo ```java import io.gitee.lisrlee.jpa.annotation.*; import io.gitee.lisrlee.query4jpa.test.entity.CoDepartmentEntity; import io.gitee.lisrlee.query4jpa.test.entity.CoEmployeeEntity; @Query(name="qryEntity", froms = { @From(name="a",entityClass = CoEmployeeEntity.class), @From(name="b",entityClass = CoDepartmentEntity.class) }, joins = {@JoinRelation( master = @JoinField(source="a",field="departmentId"), slave = @JoinField(source = "b",field="id"))}, result = @QueryResult(type = QueryResultType.ENTITY,name = "a") ) public class QoEmployeeEntity { @Filter(source = "a",field = "employeeName",strategy = FilterStrategy.FLIKE) private String employeeName; @Filter(source = "a",field = "gender",strategy = FilterStrategy.EQ) private Integer gender; @Filter(source = "b",field = "id",strategy = FilterStrategy.EQ) private Integer departmentId; public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } } ``` - 定义查询接口 ```java import io.gitee.lisrlee.query4jpa.test.qo.QoEmployeeEntity; import io.gitee.lisrlee.jpa.annotation.JpaSimpleQuery; import io.gitee.lisrlee.jpa.query.JpaQuery; import io.gitee.lisrlee.query4jpa.test.entity.CoEmployeeEntity; @JpaSimpleQuery public interface JpaQueryCustomerEntity extends JpaQuery { } ``` - 执行查询 ```java @Autowiredprivate JpaQueryCustomerEntity jpaQueryCustomer; @Test public void test0(){ QoEmployeeEntity qo = new QoEmployeeEntity(); qo.setEmployeeName("李四"); final List CoEmployeeEntityList = jpaQueryCustomer.query(qo); for (CoEmployeeEntity coEmployeeEntity : CoEmployeeEntityList) { System.out.println(coEmployeeEntity); } } ``` ##### 4.基于注解的原生SQL查询 - 定义查询条件对象qo ``` import io.gitee.lisrlee.jpa.annotation.*; @NativeQuery(name="o", froms = @FromTable( table ="co_employee", alias = "a", join = { @JoinOn(table = "co_department",alias = "b", on = { @JoinRelation( master = @JoinField(source = "a",field = "departmentId"), slave = @JoinField(source = "b",field = "id") ) } ) }), result = {@Source(source = "a",field = "*")} ) public class QoNativeEmployee { @Filter(source = "a",field = "employeeName",strategy = FilterStrategy.FLIKE) private String employeeName; @Filter(source = "a",field = "gender",strategy = FilterStrategy.EQ) private Integer gender; @Filter(source = "b",field = "id",strategy = FilterStrategy.EQ) private Integer departmentId; public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } } ``` - 定义查询接口 ```java @JpaSimpleQuery public interface JpaNativeQueryCustomer extends JpaNativeQuery { } ``` - 执行查询 ```java @Test public void testByQueryId7(){ QoNativeEmployee qo = new QoNativeEmployee(); qo.setEmployeeName("%张三%"); final List tuples = nativeQueryCustomer.queryByQo(qo); for (Tuple tuple : tuples) { System.out.println(PageMapper.pojoTuple(tuple,CoEmployeeEntity.class)); } } ``` ##### 5.基于XML文件的原生SQL查询 - 基于XML配置文件的原生SQL查询,基于注解的原生SQL查询,通过调用XXXByQo方法实现需要定义jpanativequery.xml ```xml select * from mo_merchant A and A.merchantName like :merchantName and (A.director = :director or A.telephone = :telephone) and exists(select 1 from mo_order B where B.merchantId = A.Id) order by createDate ``` jpasql/employee.xml ```xml select * from co_employee A and A.employeeName like :employeeName and A.departmentId = :departmentId and A.gender = :gender and exists(select 1 from co_project B,co_employee_project C where A.id = C.employeeId and B.id = C.projectId and C.projectId in (:projectIds)) and createTime >= :createTime0 order by createTime select A.id employee_id,A.employeeName employee_name,B.id projectId, B.project projectName from co_employee A,co_project B,co_employee_project C where A.id = C.employeeId and B.id = C.projectId and A.employeeName like :employeeName select Count(*) from co_employee A and A.employeeName like :employeeName and A.departmentId = :departmentId and A.gender = :gender and exists(select 1 from co_project B,co_employee_project C where A.id = C.employeeId and B.id = C.projectId and C.projectId in (:projectIds)) and createTime >= :createTime0 order by createTime ``` 节点说明 节点名称|属性|节点说明 :--|:--|--- native_query|namespace|根节点,namespace指定命名空间 query|id|定义一个查询,id未查询标识,在一个命名空间唯一 where|无|定义查询条件 if|test|用于测试参数是否满足条件,test属性支持SPEL和JS表达式 ifnotnull|无|用于测试参数是否为空,当相关参数部为空,条件生效 include|file|包含其他查询定义xml文件 - 定义查询条件 查询条件支持Map或Pojo,根据xml定义的sql语句中的参数定义Map的Key或Pojo的属性 ```java public class QoEmployee { private String employeeName; private Integer gender; private Timestamp createTime0; private Timestamp createTime1; private Integer departmentId; private List projectIds; public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Timestamp getCreateTime0() { return createTime0; } public void setCreateTime0(Timestamp createTime0) { this.createTime0 = createTime0; } public Timestamp getCreateTime1() { return createTime1; } public void setCreateTime1(Timestamp createTime1) { this.createTime1 = createTime1; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } public List getProjectIds() { return projectIds; } public void setProjectIds(List projectIds) { this.projectIds = projectIds; } } ``` - 定义查询接口 查询接口支持自定义方法,规则如下: ```java List queryById+namespace+id(Qo qo); Page pageQueryById+namespace+id(Qo qo); Slice sliceQueryById+namespace+id(Qo qo); JpaQueryPage pageQueryById+namespace+id(Qo qo); JpaQueryPage sliceQueryById+namespace+id(Qo qo) ; Object querySingleResultById+namespace+id(Qo qo) ; ``` > 返回结果的泛型类支持JPA Entity、Tuple、Pojo,sql语句中的字段和返回泛型类的属性之间采用宽泛映射关系,如属性名为employeeName 可以和emplyee_name、employeeName、employeename、employeeNaMe等字段建立映射关系. ```java import io.gitee.lisrlee.jpa.annotation.JpaSimpleQuery; import io.gitee.lisrlee.jpa.query.JpaNativeQuery; import io.gitee.lisrlee.jpa.query.JpaQueryPage; import io.gitee.lisrlee.query4jpa.test.qo.QoEmployee; import io.gitee.lisrlee.query4jpa.test.vo.EmployeeProjects; import io.gitee.lisrlee.query4jpa.test.entity.CoEmployeeEntity; import org.springframework.data.domain.Pageable; import java.util.List; @JpaSimpleQuery public interface JpaNativeQueryCustomer extends JpaNativeQuery { List queryByIdEmployeeQuery(QoEmployee qo); List queryByIdEmployeeQueryEmpPrj(QoEmployee qo); JpaQueryPage pageQueryByIdEmployeeQueryEmpPrj(QoEmployee qo, Pageable pageable); JpaQueryPage sliceQueryByIdEmployeeQueryEmpPrj(QoEmployee qo, Pageable pageable); Integer querySingleResultByIdEmployeeQueryCount(QoEmployee qo); } ``` - 执行查询 ```java @Autowired private JpaNativeQueryCustomer nativeQueryCustomer; @Test public void testByQueryId1(){ QoEmployee qo = new QoEmployee(); qo.setGender(1); List prjIds = new ArrayList<>(); prjIds.add(1); prjIds.add(2); qo.setProjectIds(prjIds); final List coEmployeeEntities = nativeQueryCustomer.queryByIdEmployeeQuery(qo); for (CoEmployeeEntity coEmployeeEntity : coEmployeeEntities) { System.out.println(coEmployeeEntity); } } ``` ##### 6.基于方法实体查询 @EnableJpaQuery会注册一个组件JpaQueryExecutors,基于方法实体查询采用链式调用的方式进行编写。 使用方法 ```java @SpringBootTest public class TestJpaExecutors { @Autowired private JpaQueryExecutors executors; @Test public void test0(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class, "employeeName", "gender") .where() .eq(CoEmployeeEntity.class, "id", 1) .like(CoEmployeeEntity.class, "employeeName","%s%") .query(); } @Test public void test1(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final Page query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class, "employeeName", "gender") .where() .eq(CoEmployeeEntity.class, "id", 1) .like(CoEmployeeEntity.class, "employeeName","%s%") .distinct() .pageQuery(PageRequest.of(0,10)); } @Test public void test2(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final Slice query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class, "employeeName", "gender") .where() .eq(CoEmployeeEntity.class, "id", 1) .like(CoEmployeeEntity.class, "employeeName","%s%") .sliceQuery(PageRequest.of(0,10)); } @Test public void test3(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List listTuple = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select("coEmployeeEntity.employeeName") .selectCount("CoProjectEntity.project","projectCount") .where() .on(CoEmployeeEntity.class,"id",CoEmployeeProjectEntity.class,"employeeId") .on("c.projectId","CoProjectEntity.id") .groupBy("employeeName") .having(AggregateType.COUNT,"CoProjectEntity.project", ComparisonType.GT,1) .query(); for (Tuple tuple : listTuple) { String msg = "%s %d"; System.out.println(String.format(msg, tuple.get("employeeName"), tuple.get("projectCount"))); } } @Test public void test4(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List listTuple = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select(CoEmployeeEntity::getEmployeeName) .selectCount(CoProjectEntity::getProject,"projectCount") .where() .on(CoEmployeeEntity::getId,CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId,CoProjectEntity::getId) .like(CoEmployeeEntity::getEmployeeName,"张%") .groupBy(CoEmployeeEntity::getEmployeeName) .having(AggregateType.COUNT,CoProjectEntity::getProject, ComparisonType.GT,1) .query(); for (Tuple tuple : listTuple) { String msg = "%s %d"; System.out.println(String.format(msg, tuple.get("employeeName"), tuple.get("projectCount"))); } } @Test public void test5(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List listTuple = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select(CoEmployeeEntity::getEmployeeName) .selectCount(CoProjectEntity::getProject,"projectCount") .where() .on(CoEmployeeEntity::getId,CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId,CoProjectEntity::getId) .or() .like(CoEmployeeEntity::getEmployeeName,"张%") .like(CoEmployeeEntity::getEmployeeName,"王%") .then() .groupBy(CoEmployeeEntity::getEmployeeName) .having(AggregateType.COUNT,CoProjectEntity::getProject, ComparisonType.GT,1) .query(); for (Tuple tuple : listTuple) { String msg = "%s %d"; System.out.println(String.format(msg, tuple.get("employeeName"), tuple.get("projectCount"))); } } @Test public void test6(){ final JpaQueryExecutor executor = executors.executor(CoEmployeeEntity.class); final Page pages = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class) .where() .eq(CoEmployeeEntity::getId, 1) .distinct() .pageQuery(PageRequest.of(0, 10)); for (CoEmployeeEntity coEmployeeEntity : pages.getContent()) { System.out.println(coEmployeeEntity); } } @Test public void test7(){ final JpaQueryExecutor executor = executors.executor(EmployeeProjects.class); final List List = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select("employeeId","employeeName","projectId","project") .where() .on(CoEmployeeEntity::getId, CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId, CoProjectEntity::getId) .query(); for (EmployeeProjects employeeProjects : List) { System.out.println(employeeProjects); } } @Test public void test8(){ final JpaQueryExecutor executor = executors.executor(Long.class); final Long ncount = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .selectCount(CoEmployeeProjectEntity::getId, "ncount") .where() .on(CoEmployeeEntity::getId, CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId, CoProjectEntity::getId) .querySingleResult(); System.out.println(ncount); } @Test public void test9(){ final JpaQueryExecutor executor = executors.executor(CoEmployeeEntity.class); final List listTuple = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class) .where() .notExists() .from(CoProjectEntity.class,CoEmployeeProjectEntity.class) .select(CoProjectEntity.class) .where() .on(CoEmployeeEntity::getId,CoEmployeeProjectEntity::getEmployeeId) .on(CoProjectEntity::getId,CoEmployeeProjectEntity::getProjectId) .or() .ge(CoProjectEntity::getId,1) .lt(CoProjectEntity::getId,2) .then() .then() .query(); for (CoEmployeeEntity coEmployeeEntity : listTuple) { System.out.println(coEmployeeEntity); } } @Test public void test10(){ final JpaQueryExecutor executor = executors.executor(EmployeeProjects.class); final List List = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select(EmployeeProjects.class.getConstructors()[0]) .where() .on(CoEmployeeEntity::getId, CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId, CoProjectEntity::getId) .in(CoEmployeeEntity::getDepartmentId,1,2) .orderBy(CoEmployeeEntity::getEmployeeName, OrderByType.DESC) .query(); for (EmployeeProjects employeeProjects : List) { System.out.println(employeeProjects); } } @Test public void test11(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity::getEmployeeName) .selectCase(CoEmployeeEntity::getGender) .whenEQ(0,"girl") .whenEQ(1,"boy") .otherwise("XX") .alias("gender") .then() .query(); for (Tuple tuple : query) { System.out.println(tuple.get("employeeName") + " : " + tuple.get("gender")); } } @Test public void test12(){ final JpaQueryExecutor executor = executors.executor(Tuple.class); final List List = executor.from(CoEmployeeEntity.class, CoProjectEntity.class, CoEmployeeProjectEntity.class) .select(CoEmployeeEntity::getId,"employeeId") .select(CoEmployeeEntity::getEmployeeName) .select(CoProjectEntity::getId,"projectId") .select(CoProjectEntity::getProject,"projectName") .where() .on(CoEmployeeEntity::getId, CoEmployeeProjectEntity::getEmployeeId) .on(CoEmployeeProjectEntity::getProjectId, CoProjectEntity::getId) .query(); for (Tuple tuple : List) { System.out.println(String.format("%d,%s,%d,%s", tuple.get("employeeId"), tuple.get("employeeName"), tuple.get("projectId"), tuple.get("projectName"))); } } @Test public void test13(){ final JpaQueryExecutor executor = executors.executor(CoEmployeeEntity.class); final Page query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class) .where() .in(CoEmployeeEntity::getDepartmentId, Long.class) .from(CoDepartmentEntity.class) .select(CoDepartmentEntity::getId) .where() .eq(CoDepartmentEntity::getDepartmentName, "技术部") .then() .pageQuery(PageRequest.of(0,10)); for (CoEmployeeEntity coEmployeeEntity : query) { System.out.println(coEmployeeEntity); } } @Test public void test14(){ final JpaQueryExecutor executor = executors.executor(CoEmployeeEntity.class); final List query = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class) .where() .notIn(CoEmployeeEntity::getDepartmentId, Long.class) .from(CoDepartmentEntity.class) .select(CoDepartmentEntity::getId) .where() .eq(CoDepartmentEntity::getDepartmentName, "技术部") .then() .query(); for (CoEmployeeEntity coEmployeeEntity : query) { System.out.println(coEmployeeEntity); } } @Test public void test15(){ final JpaQueryExecutor executor = executors.executor(CoEmployeeEntity.class); final Page listTuple = executor.from(CoEmployeeEntity.class) .select(CoEmployeeEntity.class) .where() .notExists() .from(CoProjectEntity.class,CoEmployeeProjectEntity.class) .select(CoProjectEntity.class) .where() .on(CoEmployeeEntity::getId,CoEmployeeProjectEntity::getEmployeeId) .on(CoProjectEntity::getId,CoEmployeeProjectEntity::getProjectId) .eq("gender",0) .then() .pageQuery(PageRequest.of(0,10)); for (CoEmployeeEntity coEmployeeEntity : listTuple) { System.out.println(coEmployeeEntity); } } } ``` #### 反馈交流 - QQ群: 1065658815 - Email:star_sky_773@163.com