In a java rest api, with spring boot, and spring-dta-jpa, db is postgresql I have a Book
entity that contains bookCopies
. These bookCopies
can be available or not. I'm trying to retrieve the book with the numbers of copies available. The books can be searched by title or author name.
I manage to get the info by adding a @Transient
field in my book entity, with the @Transient
annotation on a getNbCopiesAvailable()
method, but I'm asked to do it with @Formula
annotation, and I can't figure out how to do it.
I'm actually getting an error:
org.postgresql.util.PSQLException: ERREUR: plus d'une ligne renvoyée par une sous-requête utilisée comme une expression
// which means that several lines are sent by the sub-query
Here are my entities:
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String isbn;
@NotNull
private String title;
@JsonIgnore
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BookCopy> copyList = new ArrayList<>();
@NotNull
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "book_author",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "author_id"))
private Set<Author> authors = new HashSet<>();
@Formula("(SELECT COUNT(bc.id) FROM book b left join book_copy bc on bc.book_id = b.id WHERE bc.available = 'true' GROUP BY b.id)")
private Long nbCopiesAvailable;
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
public class BookCopy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String barcode;
private String editor;
private boolean available = true;
@ManyToOne(fetch = FetchType.LAZY)
private Book book;
Here is my repository with the query to retrieve books by title and author:
@Query("select b, a from Book b join b.authors a where b.title like %:title% and concat(a.firstName, ' ', a.lastName) like %:author%")
List<Book> findByTitleAndAuthor(@Param("title")String title,@Param("author") String author);
The @Formula("(SELECT COUNT(bc.id) FROM book b left join book_copy bc on bc.book_id = b.id WHERE bc.available = 'true' GROUP BY b.id)")
was hard to write without having syntax errors, and it's strange to me to mix native sql and jpql. But if I try to write the @Formula
in jpql it doesn't work at all.
I checked this topic that was the closest to my problem ( @Formula count on ManyToMany ), but it still doesn't work.
You need to reference the book in the where clause:
@Formula("(SELECT COUNT(bc.id) FROM book b " +
"left join book_copy bc on bc.book_id = b.id " +
"WHERE bc.available = 'true' " +
"and b.id = id " + // This is the important condititon
"GROUP BY b.id)")
private Long nbCopiesAvailable;
Otherwise your query is returning all books.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.