在本教程中,我将向您展示如何使用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();
有关每种类型的更多详细信息和示例,请访问:
- Spring JPA Derived Query example
- Spring JPA @Query example with JPQL
- Spring JPA Native Query example
让我们继续创建使用JPA存储库与多个列方法查找的项目。
JPA滤波器多列
技术 h3>
- Java 8
- Spring Boot 2(带有Spring Data JPA)
- mysql/postgresql/h2(嵌入式数据库)
- Maven 3.8.1
项目结构
让我简要解释。
-
Tutorial
数据模型类对应于实体和表教程。 -
TutorialRepository
是一个界面,可扩展用于过滤/发现方法的JpaRepository。它将在SpringBootQueryExampleApplication
中自动进行。 -
SpringBootQueryExampleApplication
是SpringBootApplication
,它实现了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.username
&spring.datasource.password
属性与您的数据库安装相同。 - Spring Boot使用Hibernate用于JPA实现,我们为MySQL或
PostgreSQLDialect
配置了PostgreSQL 的 -
spring.jpa.hibernate.ddl-auto
用于数据库初始化。我们将值设置为update
值,以便在数据库中创建一个表,该表将自动对应于定义的数据模型。对模型的任何更改也将触发表格的更新。对于生产,该属性应为validate
。
PostgreSQLDialect
- 对于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,因此默认URLhttp://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存储库通过多列方法查找
假设我们已经有教程表:
让我们创建一个与数据库交互的存储库。
在存储库中软件包,创建扩展JpaRepository
的TutorialRepository
接口。
存储库/ 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查询以从数据库过滤数据。
使用派生查询
的多个字段对于多个字段/多列,我们可以在字段/列之间使用And
,Or
关键字。
请注意,您可以根据需要加以串联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
您也可以知道:
- 如何使用this tutorial。
- 与Docker Compose: Spring Boot and MySQL example dockerize
- 使用this post上传Excel文件并将数据存储在MySQL数据库中
- 上传CSV文件并使用this post。 将数据存储在MySQL中
快乐学习!再次见。
源代码
您可以在GitHub上找到本教程的完整源代码:
进一步阅读
- Secure Spring Boot App with Spring Security & JWT Authentication
- Spring Data JPA Reference Documentation
- Spring Boot Pagination and Sorting example
Fullstack Crud App:
- Vue + Spring Boot example
- Angular 8 + Spring Boot example
- Angular 10 + Spring Boot example
- Angular 11 + Spring Boot example
- Angular 12 + Spring Boot example
- Angular 13 + Spring Boot example
- Angular 14 + Spring Boot example
- React + Spring Boot example
关联: