JPA存储库 - 通过多列查找
#网络开发人员 #编程 #java #todayilearned

在本教程中,我将向您展示如何使用JPA存储库来通过多个字段示例查找。最后,您将知道使用三种方法通过多个列过滤的方法:派生查询,jpql和本机查询。

本教程最初来自bezkoder:
https://www.bezkoder.com/jpa-filter-by-multiple-columns/

概述

用于使用自定义过滤器方法从数据库中查询数据,Spring Data JPA支持多种方法:

  • 派生查询:JPA基于查找器方法创建SQL查询并执行幕后查询。
List<Tutorial> findAll();

List<Tutorial> findByTitleContainingIgnoreCase(String title);
  • JPQL:由SQL启发。它类似于语法中的SQL查询,但针对存储在关系数据库中而不是直接与数据库表中的JPA实体对象进行操作。
@Query("SELECT t FROM Tutorial t")
List<Tutorial> findAll();

@Query("SELECT t FROM Tutorial t WHERE t.published=true")
List<Tutorial> findByPublished();
  • 本机查询:可以直接使用数据库对象和表直接操作的实际SQL查询。
@Query(value = "SELECT * FROM tutorials", nativeQuery = true)
List<Tutorial> findAllNative();

@Query(value = "SELECT * FROM tutorials t WHERE t.published=true", nativeQuery = true)
List<Tutorial> findByPublishedNative();

有关每种类型的更多详细信息和示例,请访问:

让我们继续创建使用JPA存储库与多个列方法查找的项目。

JPA滤波器多列

技术
  • Java 8
  • Spring Boot 2(带有Spring Data JPA)
  • mysql/postgresql/h2(嵌入式数据库)
  • Maven 3.8.1

项目结构

jpa-findby-multiple-fields-example

让我简要解释。

  • Tutorial数据模型类对应于实体和表教程
  • TutorialRepository是一个界面,可扩展用于过滤/发现方法的JpaRepository。它将在SpringBootQueryExampleApplication中自动进行。
  • SpringBootQueryExampleApplicationSpringBootApplication,它实现了CommandLineRunner。我们将使用TutorialRepository在此处运行查询方法。
  • Spring DataSource的配置,JPA和Hibernate In application.properties
  • pom.xml 包含Spring Boot和MySQL/PostgreSQL/H2数据库的依赖性。

创建和设置Spring Boot Project

使用Spring web tool或您的开发工具(Spring Tool Suite,Eclipse,Intellij)创建一个弹簧靴项目。

然后打开 pom.xml 并添加这些依赖性:

<!-- web for access H2 database UI -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

我们还需要再添加一个依赖项。

  • 如果您想使用 mysql
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
  • postgresql
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
  • H2 (嵌入数据库):
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

配置Spring DataSource,JPA,Hibernate

在src/main/resources文件夹下,打开应用程序。

  • 对于mysql:
spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username= root
spring.datasource.password= 123456

spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
  • 对于PostgreSQL:
spring.datasource.url= jdbc:postgresql://localhost:5432/testdb
spring.datasource.username= postgres
spring.datasource.password= 123

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
  • spring.datasource.usernamespring.datasource.password属性与您的数据库安装相同。
  • Spring Boot使用Hibernate用于JPA实现,我们为MySQL或PostgreSQLDialect配置了PostgreSQL
  • PostgreSQLDialect
  • spring.jpa.hibernate.ddl-auto用于数据库初始化。我们将值设置为update值,以便在数据库中创建一个表,该表将自动对应于定义的数据模型。对模型的任何更改也将触发表格的更新。对于生产,该属性应为validate
  • 对于H2数据库:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto= update

spring.h2.console.enabled=true
# default path: h2-console
spring.h2.console.path=/h2-ui
  • spring.datasource.url:用于内存数据库的jdbc:h2:mem:[database-name]和基于磁盘的数据库的jdbc:h2:file:[path/database-name]
  • 我们为H2数据库配置H2Dialect
  • spring.h2.console.enabled=true告诉弹簧开始H2数据库管理工具,您可以在浏览器上访问此工具:http://localhost:8080/h2-console
  • spring.h2.console.path=/h2-ui用于H2控制台的URL,因此默认URL http://localhost:8080/h2-console将更改为http://localhost:8080/h2-ui

创建实体

模型软件包中,我们定义了Tutorial类。

教程具有以下字段:ID,标题,级别,描述,已发布,创建。

模型/ tutorial.java

package com.bezkoder.spring.jpa.query.model;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "tutorials")
public class Tutorial {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  private String title;

  private String description;

  private int level;

  private boolean published;

  @Temporal(TemporalType.TIMESTAMP)
  private Date createdAt;

  public Tutorial() {

  }

  public Tutorial(String title, String description, int level, boolean published, Date createdAt) {
    this.title = title;
    this.description = description;
    this.level = level;
    this.published = published;
    this.createdAt = createdAt;
  }

  // getters and setters
}
  • @Entity注释表明该类是持久的Java类。
  • @Table注释提供了映射此实体的表。

  • @Id注释用于主键。

  • @GeneratedValue注释用于定义主键的生成策略。

  • @Temporal注释在时间戳和java.util.Date之间来回转换或时间戳记。例如,@Temporal(TemporalType.DATE)删除时间值并仅保留日期。

@Temporal(TemporalType.DATE)
private Date createdAt;

JPA存储库通过多列方法查找

假设我们已经有教程表:

jpa-find-by-multiple-columns-example

让我们创建一个与数据库交互的存储库。
存储库中软件包,创建扩展JpaRepositoryTutorialRepository接口。

存储库/ tutorialrepository.java

package com.bezkoder.spring.jpa.query.repository;

import com.bezkoder.spring.jpa.query.model.Tutorial;

public interface TutorialRepository extends JpaRepository<Tutorial, Long> {

}

在此界面中,我们将编写JPA查询以从数据库过滤数据。

使用派生查询

的多个字段

对于多个字段/多列,我们可以在字段/列之间使用AndOr关键字。
请注意,您可以根据需要加以串联33/Or

List<Tutorial> findByLevelAndPublished(int level, boolean isPublished);

List<Tutorial> findByTitleOrDescription(String title, String description);

结果:

tutorials = tutorialRepository.findByLevelAndPublished(3, true);
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=3, title=Hibernate, description=Hibernate ORM Description, level=3, published=true, createdAt=2022-04-26 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
*/

tutorials = tutorialRepository.findByTitleOrDescription("Hibernate", "Spring Data Description");
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=3, title=Hibernate, description=Hibernate ORM Description, level=3, published=true, createdAt=2022-04-26 00:00:00.0]
*/

我们可以使用以下关键字执行SQL类似的查询:

  • Like:x.field喜欢param
  • NotLike:x.Field不喜欢param
  • StartingWith:x.field like%param(带有附加的%
  • EndingWith:x.field喜欢param%(带有预读的%
  • Containing:x.field喜欢%param%(包装在%)

对于情况不敏感的查询,在SQL中,我们可以将价值强加给所有资本或较低的案例字母,然后与查询值进行比较。
Spring JPA提供IgnoreCase关键字以使用派生的查询来执行此操作。

List<Tutorial> findByTitleContainingIgnoreCase(String title);

List<Tutorial> findByTitleContainingOrDescriptionContaining(String title, String description);

List<Tutorial> findByTitleContainingIgnoreCaseAndPublished(String title, boolean isPublished);

结果:

tutorials = tutorialRepository.findByTitleContainingIgnoreCase("dat");
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
*/

String text = "ot";
tutorials = tutorialRepository.findByTitleContainingOrDescriptionContaining(text, text);
show(tutorials);
/*
Tutorial [id=2, title=Java Spring Boot, description=Spring Framework Description, level=1, published=false, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=4, title=Spring Boot, description=Spring Boot Description, level=2, published=false, createdAt=2022-04-26 00:00:00.0]
*/

tutorials = tutorialRepository.findByTitleContainingAndPublished("ring", true);
// or
// tutorials = tutorialRepository.findByTitleContainingIgnoreCaseAndPublished("spring", true);
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
Tutorial [id=6, title=Spring Batch, description=Spring Batch Description, level=4, published=true, createdAt=2022-05-19 00:00:00.0]
*/

使用JPQL

进行多个字段

让我们使用@Query注释来创建Spring JPA查询,并在其中关键字。

@Query("SELECT t FROM Tutorial t WHERE LOWER(t.title) LIKE LOWER(CONCAT('%', :keyword,'%')) OR LOWER(t.description) LIKE LOWER(CONCAT('%', :keyword,'%'))")
List<Tutorial> findByTitleContainingOrDescriptionContainingCaseInsensitive(String keyword);

@Query("SELECT t FROM Tutorial t WHERE LOWER(t.title) LIKE LOWER(CONCAT('%', :title,'%')) AND t.published=:isPublished")
List<Tutorial> findByTitleContainingCaseInsensitiveAndPublished(String title, boolean isPublished);

结果:

tutorials = tutorialRepository.findByTitleContainingOrDescriptionContainingCaseInsensitive("data");
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
*/

tutorials = tutorialRepository.findByTitleContainingCaseInsensitiveAndPublished("spring", true);
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
Tutorial [id=6, title=Spring Batch, description=Spring Batch Description, level=4, published=true, createdAt=2022-05-19 00:00:00.0]
*/

使用本机查询

的多个字段

我们还使用@Query注释来创建Spring JPA本机查询,并在其中关键字。

@Query(value = "SELECT * FROM tutorials t WHERE LOWER(t.title) LIKE LOWER(CONCAT('%', :keyword,'%')) OR LOWER(t.description) LIKE LOWER(CONCAT('%', :keyword,'%'))", nativeQuery = true)
List<Tutorial> findByTitleContainingOrDescriptionContainingCaseInsensitive(String keyword);

  @Query(value = "SELECT * FROM tutorials t WHERE LOWER(t.title) LIKE LOWER(CONCAT('%', :title,'%')) AND t.published=:isPublished", nativeQuery = true)
List<Tutorial> findByTitleContainingCaseInsensitiveAndPublished(String title, boolean isPublished);

结果:

tutorials = tutorialRepository.findByTitleContainingOrDescriptionContainingCaseInsensitive("data");
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
*/

tutorials = tutorialRepository.findByTitleContainingCaseInsensitiveAndPublished("spring", true);
show(tutorials);
/*
Tutorial [id=1, title=Spring Data, description=Spring Data Description, level=3, published=true, createdAt=2022-03-11 00:00:00.0]
Tutorial [id=5, title=Spring JPA, description=Spring Data JPA Description, level=3, published=true, createdAt=2022-05-19 00:00:00.0]
Tutorial [id=6, title=Spring Batch, description=Spring Batch Description, level=4, published=true, createdAt=2022-05-19 00:00:00.0]
*/

通过多列项目运行JPA过滤器

让我们打开SpringJpaRepositoryQueryExampleApplication.java,我们将实现CommandLineRunner和autowire TutorialRepository接口以在此处运行JPA查询方法。

package com.bezkoder.spring.jpa.query;

// import ...

@SpringBootApplication
public class SpringJpaRepositoryQueryExampleApplication implements CommandLineRunner {

  @Autowired
  TutorialRepository tutorialRepository;

  public static void main(String[] args) {
    SpringApplication.run(SpringJpaRepositoryQueryExampleApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    // call tutorialRepository methods here
  }

  private void show(List<Tutorial> tutorials) {
    tutorials.forEach(System.out::println);
  }
}

结论

今天,我们已经知道如何使用JPA存储库在Spring Boot示例中使用派生查询,JPQL和本机查询在Spring Boot示例中的多个列查找/过滤器。
我们可以查询由逻辑运算符(和OR)分隔的任何数量的字段。

您可以继续使用:
继续编写crud rest apis Spring Boot, Spring Data JPA – Rest CRUD API example

如果要为JPA存储库编写单元测试:
Spring Boot Unit Test for JPA Repository with @DataJpaTest

您也可以知道:

快乐学习!再次见。

源代码

您可以在GitHub上找到本教程的完整源代码:

进一步阅读

Fullstack Crud App:

关联: