# 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