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 筛选出需要的实例。

阅读剩余 73%

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

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

相关文章

  • Java实现从jar包中读取指定文件的方法

    当我们需要从Java的一个jar包中读取指定的文件时,可以采用以下的几种方法,下面将针对每种方法进行详细讲解。 方法一:使用ClassLoader.getResourceAsStream()方法 该方法可以从一个jar包中直接读取文件的输入流,可以通过下面的步骤来实现: 确定需要读取的文件名,如 config.properties。 获取到当前线程的Clas…

    Java 2023年5月19日
    00
  • Spring MVC学习之DispatcherServlet请求处理详析

    Spring MVC学习之DispatcherServlet请求处理详析 Spring MVC 是一个基于 Java 的 Web 框架,它是 Spring Framework 的一部分。Spring MVC 提供了一种基于 MVC(Model-View-Controller)模式的 Web 应用程序开发方式。在 Spring MVC 中,Dispatcher…

    Java 2023年5月18日
    00
  • 站长必看!赚钱网站资源贴

    站长必看!赚钱网站资源贴 一、引言 作为一个网站站长,赚钱是我们始终追求的一个目标。然而,在众多的网络赚钱方法中选择适合自己的方式并不是一件容易的事情。因此,本文针对网站站长提供了一些有用的资源和建议,帮助您更加容易地赚钱。 二、网站广告 网站广告是一种常见的赚钱方式,下面列出几种常见的广告形式: 1. 横幅广告 横幅广告是在页面的顶部或底部显示的广告条,通…

    Java 2023年6月16日
    00
  • Spring Boot系列教程之日志配置

    SpringBoot系列教程之日志配置 在SpringBoot项目中,对日志进行定制和配置是非常重要的。通过合理的日志配置,可以对程序进行细致的排查和问题定位。本文将针对SpringBoot项目中的日志配置进行详细的讲解。 1. 了解logback和log4j的区别 在SpringBoot默认的日志框架中,使用的是logback。但是在实际项目中,也有部分使…

    Java 2023年5月15日
    00
  • SpringBoot整合JPA方法及配置解析

    关于SpringBoot整合JPA方法及配置解析的完整攻略,我给你详细讲解一下。 什么是JPA JPA(Java Persistence API)是Sun为JavaEE开发量身定制的一套API,用于处理对象与关系数据库的映射(Object Relational Mapping)问题。 通过JPA,我们可以使用Java类和对象来操作关系型数据库,而不需要写直接…

    Java 2023年5月20日
    00
  • mybatis plus自动生成器解析(及遇到的坑)

    下面我将为你详细讲解 Mybatis Plus 自动生成器解析及遇到的坑。 1. 简介 Mybatis Plus 是一款基于 Mybatis 的快速开发框架,提供了常用的 CRUD 操作、分页、逻辑删除等功能,大大减少了代码量,提升了开发效率。而其中的代码生成器,更是可以帮助我们一键生成实体、Mapper、Service、Controller 等文件,减少了…

    Java 2023年6月2日
    00
  • JDBC 数据库常用连接 链接字符串

    当我们使用Java来操作数据库时,需要使用到JDBC API。而在使用JDBC API时,我们需要对数据库进行连接,与数据库建立起联系,这个过程称为“连接(Connect)”。 连接包括几个关键步骤: 1.导入JDBC相关的Jar包 我们需要导入JDBC相关的Jar包才能够使用JDBC API。常用的Jar包有mysql-connector-java,它是M…

    Java 2023年6月16日
    00
  • Spring Boot 整合持久层之JdbcTemplate

    下面是详细讲解”Spring Boot 整合持久层之 JdbcTemplate” 的完整攻略: JdbcTemplate 简介 JdbcTemplate 是 Spring Framework 提供的一种针对 JDBC 操作的一个简化封装框架,帮助开发者摆脱繁琐的 JDBC 操作代码,提供了一组方法来方便地操作数据库。 JdbcTemplate内部封装了Jdb…

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