Spring Boot JPA的查詢語句
之前的文章中,我們講解了如何使用Spring Boot JPA, 在Spring Boot JPA中我們可通過構建查詢方法或者通過@Query注解來構建查詢語句,本文我們將會更詳細的討論查詢語句的構建。
准備工作
首先我們需要添加依賴,這里我們還是使用H2內存數據庫:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
我們創建一個Entity:
@Data
@Entity
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String title;
private String director;
private String rating;
private int duration;
}
構建初始化data.sql:
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);
構建Repository:
public interface MovieRepository extends JpaRepository<Movie, Long> {
}
Containing, Contains, IsContaining 和 Like
如果我們想要構建模下面的模糊查詢語句:
SELECT * FROM movie WHERE title LIKE '%in%';
我們可以這樣寫:
List<Movie> findByTitleContaining(String title);
List<Movie> findByTitleContains(String title);
List<Movie> findByTitleIsContaining(String title);
將上面的語句添加到Repository中就夠了。
我們看下怎么測試:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {QueryApp.class})
public class MovieRepositoryTest {
@Autowired
private MovieRepository movieRepository;
@Test
public void TestMovieQuery(){
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 關鍵詞,我們可以這樣用:
List<Movie> findByTitleLike(String title);
測試代碼:
results = movieRepository.findByTitleLike("%in%");
assertEquals(3, results.size());
StartsWith
如果我們需要實現下面這條SQL:
SELECT * FROM Movie WHERE Rating LIKE 'PG%';
我們可以這樣使用:
List<Movie> findByRatingStartsWith(String rating);
測試代碼如下:
List<Movie> results = movieRepository.findByRatingStartsWith("PG");
assertEquals(6, results.size());
EndsWith
如果我們要實現下面的SQL:
SELECT * FROM Movie WHERE director LIKE '%Burton';
可以這樣構建:
List<Movie> findByDirectorEndsWith(String director);
測試代碼如下:
List<Movie> results = movieRepository.findByDirectorEndsWith("Burton");
assertEquals(1, results.size());
大小寫不敏感
要是想實現大小不敏感的功能我們可以這樣:
List<Movie> findByTitleContainingIgnoreCase(String title);
測試代碼如下:
List<Movie> results = movieRepository.findByTitleContainingIgnoreCase("the");
assertEquals(2, results.size());
Not
要想實現Not的功能,我們可以使用NotContains, NotContaining, 和 NotLike關鍵詞:
List<Movie> findByRatingNotContaining(String rating);
測試代碼如下:
List<Movie> results = movieRepository.findByRatingNotContaining("PG");
assertEquals(1, results.size());
NotLike:
List<Movie> findByDirectorNotLike(String director);
測試代碼如下:
List<Movie> results = movieRepository.findByDirectorNotLike("An%");
assertEquals(5, results.size());
@Query
如果我們要實現比較復雜的查詢功能,我們可以使用@Query,下面是一個命名參數的使用:
@Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%")
List<Movie> searchByTitleLike(@Param("title") String title);
如果有多個參數,我們可以這樣指定參數的順序:
@Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%")
List<Movie> searchByRatingStartsWith(String rating);
下面是測試代碼:
List<Movie> results = movieRepository.searchByRatingStartsWith("PG");
assertEquals(6, results.size());
在Spring Boot2.4之后,我們可以使用SpEL表達式:
@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}")
List<Movie> searchByDirectorEndsWith(String director);
看下怎么使用:
List<Movie> results = movieRepository.searchByDirectorEndsWith("Burton");
assertEquals(1, results.size());
更多教程請參考 flydean的博客