1. 概述
在这个快速教程中,我们将介绍在春季JPA存储库中创建类似查询的不同方法。
我们将首先查看在创建查询方法时可以使用的各种关键字。然后,我们将使用命名和有序参数覆盖@Query注释。
2. 设置
对于我们的示例,我们将查询一个 movie 表。
让我们定义我们的电影实体:
@Entity
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String title;
private String director;
private String rating;
private int duration;
// standard getters and setters
}
定义了我们的 Movie 实体后,让我们创建一些示例插入语句:
INSERT INTO movie(id, title, director, rating, duration)
VALUES(1, 'Godzilla: King of the Monsters', ' Michael Dougherty', 'PG-13', 132);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(2, 'Avengers: Endgame', 'Anthony Russo', 'PG-13', 181);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(3, 'Captain Marvel', 'Anna Boden', 'PG-13', 123);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(4, 'Dumbo', 'Tim Burton', 'PG', 112);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(5, 'Booksmart', 'Olivia Wilde', 'R', 102);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(6, 'Aladdin', 'Guy Ritchie', 'PG', 128);
INSERT INTO movie(id, title, director, rating, duration)
VALUES(7, 'The Sun Is Also a Star', 'Ry Russo-Young', 'PG-13', 100);
3. 喜欢的查询方法
对于许多简单的 LIKE 查询方案,我们可以利用各种关键字在存储库中创建查询方法。
现在让我们来探索它们。
3.1. 包含、包含、包含和类似
让我们看一下如何使用查询方法执行以下 LIKE 查询:
SELECT * FROM movie WHERE title LIKE '%in%';
首先,让我们使用包含、包含和包含来定义查询方法:
List<Movie> findByTitleContaining(String title);
List<Movie> findByTitleContains(String title);
List<Movie> findByTitleIsContaining(String title);
让我们用以下部分标题调用我们的查询方法:
List<Movie> results = movieRepository.findByTitleContaining("in");
assertEquals(3, results.size());
results = movieRepository.findByTitleIsContaining("in");
assertEquals(3, results.size());
results = movieRepository.findByTitleContains("in");
assertEquals(3, results.size());
我们可以预期这三种方法中的每一个都会返回相同的结果。
Spring还为我们提供了一个 Like 关键字,但它的行为略有不同,因为我们需要在搜索参数中提供通配符。
让我们定义一个 LIKE 查询方法:
List<Movie> findByTitleLike(String title);
现在,我们将使用与之前相同的值调用 findByTitleLike 方法,但包括通配符:
results = movieRepository.findByTitleLike("%in%");
assertEquals(3, results.size());
3.2. 启动与
让我们看一下以下查询:
SELECT * FROM Movie WHERE Rating LIKE 'PG%';
我们将使用“启动与”关键字来创建查询方法:
List<Movie> findByRatingStartsWith(String rating);
定义我们的方法后,让我们用值PG来调用它:
List<Movie> results = movieRepository.findByRatingStartsWith("PG");
assertEquals(6, results.size());
3.3. 结束
春天为我们提供了与“结束与”关键字相反的功能。
让我们考虑这个查询:
SELECT * FROM Movie WHERE director LIKE '%Burton';
现在,我们将定义一个“结束与”查询方法:
List<Movie> findByDirectorEndsWith(String director);
一旦我们定义了我们的方法,让我们用Burton参数来调用它:
List<Movie> results = movieRepository.findByDirectorEndsWith("Burton");
assertEquals(1, results.size());
3.4. 不区分大小写
我们经常希望找到包含特定字符串的所有记录,而不管大小写。在 SQL 中,我们可以通过强制列全部为大写或小写字母并为正在查询的值提供相同的值来实现此目的。
使用春季JPA,我们可以将忽略大小写关键字与我们的其他关键字之一结合使用:
List<Movie> findByTitleContainingIgnoreCase(String title);
现在,我们可以调用带有 的方法,并期望获得包含小写和大写结果的结果:
List<Movie> results = movieRepository.findByTitleContainingIgnoreCase("the");
assertEquals(2, results.size());
3.5. 不
有时,我们希望查找不包含特定字符串的所有记录。我们可以使用“不包含”、“不包含”和“不喜欢”关键字来执行此操作。
让我们使用“不包含”来定义一个查询,以查找评级不包含 PG 的电影:
List<Movie> findByRatingNotContaining(String rating);
现在让我们调用新定义的方法:
List<Movie> results = movieRepository.findByRatingNotContaining("PG");
assertEquals(1, results.size());
为了实现查找导演姓名不以特定字符串开头的记录的功能,我们将使用 NotLike 关键字来保留对通配符放置的控制:
List<Movie> findByDirectorNotLike(String director);
最后,让我们调用该方法来查找导演名称以 An 以外的其他内容开头的所有电影:
List<Movie> results = movieRepository.findByDirectorNotLike("An%");
assertEquals(5, results.size());
我们可以以类似的方式使用 NotLike 来完成“不与 EndsWith”结合使用的功能。
4. 使用@Query
有时,我们需要创建对于查询方法来说过于复杂的查询,或者会导致方法名称长得离谱。在这些情况下,我们可以使用@Query注释来查询我们的数据库。
4.1. 命名参数
为了进行比较,我们将创建一个查询,该查询等效于我们之前定义的 findByTitle 包含方法:
@Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%")
List<Movie> searchByTitleLike(@Param("title") String title);
我们在提供的查询中包含通配符。@Param注释在这里很重要,因为我们使用的是命名参数。
4.2. 有序参数
除了命名参数之外,我们还可以在查询中使用有序参数:
@Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%")
List<Movie> searchByRatingStartsWith(String rating);
我们可以控制通配符,因此此查询等效于“查找通过评级StartsWith”查询方法。
让我们找到所有评级以PG开头的电影:
List<Movie> results = movieRepository.searchByRatingStartsWith("PG");
assertEquals(6, results.size());
当我们在具有不受信任数据的 LIKE 查询中使用有序参数时,我们应该转义传入的搜索值。
如果我们使用的是弹簧启动 2.4.1 或更高版本,我们可以使用 SpEL 转义方法:
@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}")
List<Movie> searchByDirectorEndsWith(String director);
现在,让我们用值 Burton 调用我们的方法:
List<Movie> results = movieRepository.searchByDirectorEndsWith("Burton");
assertEquals(1, results.size());
5. 结论
在这篇简短的文章中,我们学习了如何在春季JPA存储库中创建 LIKE 查询。
首先,我们学习了如何使用提供的关键字来创建查询方法。
然后,我们学习了如何使用具有命名参数和有序参数的@Query参数来完成相同的任务。
完整的示例代码可在 GitHub 上找到。