[Spring Data JPA] Custom Query
Basic Query
public interface BookRepository extends CrudRepository<Book, Long> {
@Query("SELECT b from Book b WHERE b.available = true")
List<Book> findAvailableBooks();
}
List<Book> availableBooks = bookRepository.findAvailableBooks();
for (Book book : availableBooks) {
System.out.println(book.toString());
}
It is also possible to write Query in other format:
@Query("FROM Book b WHERE b.available = true")
@Query(value="SELECT * FROM Book b WHERE b.available = 1", nativeQuery = true)
Params Query:
@Query("SELECT b FROM Book b WHERE b.author = ?1")
List<Book> findByAuthor(String author);
List<Book> authorBooks = bookRepository.findByAuthor("Jane Austen");
@Query("SELECT b FROM Book b WHERE b.author = ?1 AND b.available = ?2")
List<Book> findByAuthorAndAvailability(String author, boolean available);
List<Book> authorAvailableBooks = bookRepository.findByAuthorAndAvailability("William H. Gass", true);
Reference Params by name:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
@Query("SELECT b FROM Book b WHERE b.author = :author")
List<Book> findByAuthor2(@Param("author") String author);
@Query("SELECT b FROM Book b WHERE b.author = :author AND b.available = :avail ORDER BY title")
List<Book> findByAuthorAndAvailability2(@Param("author") String author, @Param("avail") boolean availability);
Update Operation:
Have to add @Transactional annotation to the Class or Method. Otherwise, will throw error.
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import javax.transaction.Transactional;
...
@Transactional
public interface BookRepository extends CrudRepository<Book, Long> {
@Modifying
@Query("UPDATE Book b SET b.title = :title WHERE b.bookId = :id")
int updateTitleById(@Param("title") String title, @Param("id") Long bookId);
}
bookRepository.updateTitleById("The Tempest", 3L);
Delete:
@Transactional
@Modifying
@Query("DELETE FROM Book b WHERE b.title = ?1")
void deleteBookByTitle(String title);
Using Named Queries from a Properties File:
1. In resources folder, create a new folder called `META-INF`
2. Under new folder, create a new file called `jpa-named-queries.properties`
Book.findAllNamedQuery=SELECT b FROM Book b ORDER BY b.rating DESC
Book.findByTitleNamedQuery=SELECT b FROM Book b WHERE b.title = ?1
Book.findByAuthorNativeNamedQuery=SELECT * FROM Book b WHERE b.author = :author
3. Add code in respository
List<Book> findAllNamedQuery();
List<Book> findByTitleNamedQuery(String title);
@Query(nativeQuery = true)
List<Book> findByAuthorNativeNamedQuery(@Param("author")String author);
List<Book> books3 = bookRepository.findByAuthorNativeNamedQuery("Leo Tolstoy");
Defining Named Queries in XML:
1. Under resources/META-INF folder, add new file orm.xml
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_2_0.xsd ">
<!--find all books order by price descending-->
<named-query name="Book.findAllXML">
<query>SELECT b FROM Book b ORDER BY b.rating DESC</query>
</named-query>
<!--find books by minimum rating-->
<named-query name="Book.findByMinRatingXML">
<query>SELECT b FROM Book b WHERE b.rating >= ?1 ORDER BY b.rating</query>
</named-query>
<!--native SQL query to find a book by author-->
<named-native-query name="Book.findByAuthorNativeXML"
result-class="com.skillsoft.springdatajpa.model.Book">
<query>SELECT * FROM book b WHERE b.author = :author</query>
</named-native-query>
</entity-mappings>
2. Add those methods into repository
Defining Named Queries in Java Files:
package com.skillsoft.springdatajpa.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@NamedQuery(name = "Book.findAvailableBooksJPQL", query="SELECT b FROM Book b WHERE b.available = 1")
@NamedQuery(name = "Book.findByRatingJPQL" ,query = "SELECT b FROM Book b WHERE b.rating >=?1")
@NamedNativeQuery(name="Book.findByTitleNative", query = "SELECT * FROM book b WHERE b.title = :title", resultClass = Book.class)
@Table(name = "Book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long bookId;
private String title;
private String author;
private int rating;
private boolean available;
public Book() {
}
public Book(String title, String author, int rating, boolean available) {
this.title = title;
this.author = author;
this.rating = rating;
this.available = available;
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", title='" + title + '\'' +
", author='" + author + '\'' +
", rating=" + rating +
", available=" + available +
'}'+'\n';
}
}
2. Update code in repository
@Query(nativeQuery = true)
List<Book> findByTitleNative(@Param("title")String title);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2021-05-20 [AWS] ElasticSearch, Sync data between DynamoDB and ElasticSearch by using DyanmoDB Stream
2020-05-20 [Functional Programming] EitherToTask transform
2020-05-20 [Functional Programming] Traverse Task and Either
2019-05-20 [AngularJS] Decorator pattern for code reuse
2019-05-20 [Functional Programming] Async ADT
2016-05-20 [AWS S3] Hosting a Static Website on Amazon S3
2016-05-20 [PWA] 15. Using The IDB Cache And Display Entries