[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);

 

posted @ 2022-05-20 15:59  Zhentiw  阅读(119)  评论(0编辑  收藏  举报