jpa - 如何拦截和修改JPA生成的SQL语句?
问题描述
我想知道是否有一种方法可以优化生成 JPA 查询(JPQL)的过程,而不是使用原生的。
为简单起见,我的模型如下所示:
@Entity
@Table(name = "b_books")
public class Book {
@Id
@Column(name = "book_id", updatable = false, nullable = false, unique = true)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="book_generator")
@SequenceGenerator(name="book_generator", sequenceName = "books_seq", allocationSize=1)
private Integer id;
@Column(name = "book_titl_tx")
private String title;
private int yearOfPublication;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "b_book_authors",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "auth_id"))
private List<Author> authors = new ArrayList<Author>();
//getter, setters, etc
}
@Entity
@Table(name = "b_authors")
public class Author {
@Id
@Column(name = "auth_id", nullable = false, unique = true)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="authors_generator")
@SequenceGenerator(name="authors_generator", sequenceName = "authors_seq", allocationSize=1)
private Integer id;
@Column(name = "auth_last_name_tx")
private String lastName;
@ManyToMany(mappedBy = "authors")
private List<Book> books = new ArrayList<Book>();
//getters, setters, etc
}
在数据库方面,我有三个表:
- B_BOOKS
- B_AUTHORS
- B_BOOK_AUTHORS 持有多对多关系
我想向数据库查询每位作者的书籍数量
public interface AuthorRepository extends JpaRepository<Author, Integer>{
@Query(value = "SELECT a.lastName AS lastName, " +
" COUNT(a) AS booksCount" +
" FROM Author AS a " +
" LEFT JOIN a.books AS b" +
" GROUP BY a.lastName")
List<IAuthorInfo> getAuthorInfo();
}
我正在使用基于界面的投影
public interface IAuthorInfo {
String getLastName();
Integer getBooksCount();
}
现在主要问题是:使用这种模型 JPA 生成的查询有一个冗余的 JOIN,如何摆脱它?
实际的:
SELECT
author0_.auth_last_name_tx AS col_2_0_,
COUNT(author0_.auth_id) AS col_3_0_
FROM
admin.b_authors author0_
LEFT OUTER JOIN admin.b_book_authors books1_ ON author0_.auth_id = books1_.auth_id
LEFT OUTER JOIN admin.b_books book2_ ON books1_.book_id = book2_.book_id
GROUP BY
author0_.auth_last_name_tx
预期的
SELECT
author0_.auth_last_name_tx AS col_2_0_,
COUNT(author0_.auth_id) AS col_3_0_
FROM
admin.b_authors author0_
LEFT OUTER JOIN admin.b_book_authors books1_ ON author0_.auth_id = books1_.auth_id
GROUP BY
author0_.auth_last_name_tx
解决方案
您可以使用以下size()
功能:
SELECT a.lastName AS lastName, size(a.books) AS booksCount FROM Author AS a GROUP BY a.lastName
我没有测试过,但我想LEFT JOIN a.books AS b
从您的查询中删除 可以解决这个问题。
推荐阅读
- vba - 自定义 Outlook 宏仅在 VBA 编辑器中运行
- elasticsearch - 如何将索引从旧服务器迁移到elasticsearch的新服务器
- r - 扩展网格以在 R 中生成新数据集
- react-native - 渲染没有返回任何内容。这通常意味着缺少 return 语句。或者,不渲染任何内容,返回 null。React-native,异步存储
- c++ - 使用 lock_guard 采用的互斥锁可以导致 UB 吗?
- json - 我可以将回调函数包装到另一个函数中以从中返回值吗?
- c++ - 如何使用类获取矩形的面积?
- python - 如何创建具有路线距离的颜色图
- flutter - 如何在 HashMap 的 ArrayList 中添加元素?飞镖和颤振
- javascript - 查找一个国家/州的所有城市或从 JSON 数据中查找给定城市的州/国家