Spring Data JPA系列QueryByExampleExecutor使用详解

Spring Data JPA系列QueryByExampleExecutor使用详解

简介

Spring Data JPA 是 Spring Data 的一个模块,它通过 JPA 技术为程序开发人员提供了方便、快捷的持久化支持。Query By Example(QBE)是 Spring Data JPA 模块中的一部分,允许您根据已知的实体对象创建查询样例,可以通过 QBE 生成基于实体属性的动态查询语句。

QueryByExampleExecutor

QueryByExampleExecutor 接口提供了按实例的查询语法。该接口包含两个方法:

<S extends T> Optional<S> findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);

其中,findOne() 方法将返回与示例符合的第一个实体。如果没有找到任何实体,则返回 Optional 的空实例。

findAll() 方法将根据示例返回一个 Iterable 集合。如果没有找到任何实体,则返回空的 Iterable 实例。

ExampleMatcher

ExampleMatcher 是 Query By Example 的核心部分,它描述了对特定类型的示例应如何进行匹配。 ExampleMatcher 可以在 Query 接口级别或在基础 CRUD Repository 接口级别对应用程序执行的查询进行全局配置。

ExampleMatcher.Builder 是用于实例化 ExampleMatcher 的静态构建器。

以下代码片段说明了如何构建 ExampleMatcher 对象:

ExampleMatcher matcher = ExampleMatcher.matching()
        .withIgnorePaths("field1", "field2")
        .withMatcher("field3", matcher -> matcher.startsWith())
        .withMatcher("field4", matcher -> matcher.endsWith())
        .withMatcher("field5", matcher -> matcher.contains())
        .withMatcher("field6", matcher -> matcher.matches());

上述 ExampleMatcher 会执行以下操作:

  • 忽略名为 field1 和 field2 的属性。
  • 特定字段应以其字段值开头筛选。
  • 特定字段应以其字段值结尾。
  • 特定字段应包含其字段值。
  • 特定字段应具有与其字段值完全匹配的值。

示例1 方法级别

考虑以下 Entity:

@Entity
@Table(name = "employee")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id", nullable = false)
    private Department department;

    // ... 省略其他字段和方法
}

现在我们想按名称模糊搜索 Employee,请使用 QBE 实现此目的。

Employee employee = new Employee();
employee.setName("mark");
ExampleMatcher matcher = ExampleMatcher.matching()
        .withMatcher("name", match -> match.contains());
Example<Employee> example = Example.of(employee, matcher);
List<Employee> employees = employeeRepository.findAll(example);

上面的示例将返回符合 name 属性包含“mark”子字符串的 Employee 实例的所有结果。请注意,我们使用的是 Example 类的 of() 工厂方法来创建 Example 实例。

示例2 Query 接口级别

考虑以下 Employee Entity:

@Entity
@Table(name = "employee")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id", nullable = false)
    private Department department;

    // ... 省略其他字段和方法
}

现在我们想按部门名称以及部门经理姓名搜索 Employee,请使用 QBE 实现此目的。

首先,我们需要创建一个自定义的查询接口,这将包含我们要使用的自定义查询方法。

public interface EmployeeRepositoryCustom {

    List<Employee> findByDepartmentAndManager(String departmentName, String managerName);
}

其次,我们需要创建一个实现,它将包含我们要使用的自定义查询方法的查询方法。

@Repository
public class EmployeeRepositoryCustomImpl implements EmployeeRepositoryCustom {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<Employee> findByDepartmentAndManager(String departmentName, String managerName) {
        Department department = new Department();
        department.setName(departmentName);
        Employee manager = new Employee();
        manager.setName(managerName);
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withIgnorePaths("id")
                .withMatcher("name", match -> match.contains());
        Example<Employee> example = Example.of(manager, matcher);
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Employee> query = criteriaBuilder.createQuery(Employee.class);
        Root<Employee> root = query.from(Employee.class);
        Join<Employee, Department> join = root.join("department");
        query.select(root)
                .where(criteriaBuilder.equal(join.get("name"), department.getName()),
                        criteriaBuilder.equal(root.get("manager"), manager));
        return entityManager.createQuery(query).getResultList();
    }
}

这将对名为“departmentName”的部门以及名为“managerName”的经理进行搜索。这里我们将经理实例自己创建 Example,以便可以将 Example 用于其名称。我们同时使用 QueryDSL Lambda 表达式和 JPA CriteriaBuilder 构建搜索条件和搜索结果。

最后,我们需要创建 CRUD Repository 接口和实体的 Repository 实现类。

@Transactional(readOnly = true)
public interface EmployeeRepository extends JpaRepository<Employee, Long>, QueryByExampleExecutor<Employee>, EmployeeRepositoryCustom {
}
@Repository
@Transactional(readOnly = true)
public class EmployeeRepositoryImpl extends SimpleJpaRepository<Employee, Long> implements EmployeeRepository {

    public EmployeeRepositoryImpl(EntityManager em) {
        super(Employee.class, em);
    }
}

现在,我们可以在我们的应用程序中调用我们的函数,并且将返回当前按照特定条件过滤的搜索结果集。

List<Employee> employees = employeeRepository.findByDepartmentAndManager("IT", "Mark");

总结

这篇文档介绍了 Spring Data JPA Query By Example Executor 和 ExampleMatcher 接口的细节。QueryByExampleExecutor 提供了按实例的查询语法,并允许您根据已知的实体对象创建查询样例。 ExampleMatcher 用于对如何对示例进行匹配进行描述。最后,我们提供了两个示例,演示如何使用 QBE 筛选出需要的实例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Data JPA系列QueryByExampleExecutor使用详解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java通过httpclient比较重定向和请求转发

    Java通过httpclient比较重定向和请求转发的攻略如下: 什么是重定向和请求转发 首先我们要明确一下重定向和请求转发的概念。 重定向是服务器将请求重定向到另一个URL,常见的状态码有301和302,301表示永久重定向,302表示临时重定向。 请求转发是服务器将请求发送到另一个URL的资源,但客户端并不知道这个过程,因为浏览器只看到转发前的URL。 …

    Java 2023年6月15日
    00
  • java算法题解Leetcode763划分字母区间示例

    下面是“java算法题解Leetcode763划分字母区间示例”的完整攻略。 题目描述 给定一个仅包含小写字母的字符串 S,将字符串 S 划分为尽可能多的区间,使得每个字母最多出现在一个区间中,求区间的个数。 解题思路 首先,我们可以使用hashmap记录每个字母最后出现的位置,然后使用两个指针,分别记录当前合法区间的左右端点。 接着,我们遍历字符串S,记录…

    Java 2023年5月19日
    00
  • CCF考试试题之门禁系统java解题代码

    关于“CCF考试试题之门禁系统java解题代码”的完整攻略,请看下面的详细讲解。 一、题目背景 这是一道CCF认证考试的试题,要求我们写一段代码实现一个门禁系统。门禁系统需要记录人员的姓名和进出时间,并按照时间排序输出人员进入和离开的记录。 二、解题思路 首先,我们需要定义一个类,来存储每位人员的姓名和进出时间。 class AccessRecord { S…

    Java 2023年5月24日
    00
  • javamail实现注册激活邮件

    JavaMail 是 Java 的一个邮件处理 API,可以用来实现邮件的收发、抄送、群发、附件等操作。利用 JavaMail 实现注册激活邮件功能是一个常见的需求。以下是实现该功能的详细攻略。 配置 pom.xml 文件 首先需要在项目的 pom.xml 文件中添加 JavaMail 依赖,这里以最新版本 1.6.2 为例: <dependency&…

    Java 2023年6月15日
    00
  • SpringMVC注解@RequestParam方法原理解析

    以下是关于“SpringMVC注解@RequestParam方法原理解析”的完整攻略,其中包含两个示例。 SpringMVC注解@RequestParam方法原理解析 SpringMVC是一个基于Java的Web框架,它可以帮助我们快速开发Web应用程序。@RequestParam是SpringMVC中的一个注解,它可以帮助我们获取HTTP请求中的参数。本文…

    Java 2023年5月17日
    00
  • 浅谈JSP serverlet的区别与联系

    浅谈JSP和Servlet的区别与联系 JSP(Java Server Pages)和Servlet是Java Web开发中常见的两种技术。JSP是一种动态网页开发技术,它允许在HTML网页中嵌入Java代码,从而实现页面数据的动态生成和交互性的实现。而Servlet则是Java Web应用程序的一个组成部分,是运行在Web服务器上的Java程序,它可以在W…

    Java 2023年6月15日
    00
  • Mybatis实现动态增删改查功能的示例代码

    让我们来详细讲解”Mybatis实现动态增删改查功能的示例代码”的完整攻略吧。 1. 引入Mybatis-Plus依赖 首先,我们需要在项目中引入Mybatis-Plus的依赖。在pom.xml文件中添加以下内容: <dependency> <groupId>com.baomidou</groupId> <artif…

    Java 2023年5月20日
    00
  • MyBatis动态SQL标签用法实例详解

    MyBatis动态SQL标签用法实例详解 本文介绍了MyBatis中动态SQL标签的用法及示例。动态SQL标签允许我们根据不同的条件动态生成SQL语句,让SQL语句变得更加灵活和通用。下面分别介绍了if、choose、foreach、when、otherwise五种常用的动态SQL标签。 if标签 if标签可以根据条件判断是否要拼接SQL语句。示例代码如下:…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部