Grails中hasMany关联场景下如何避免N+1查询问题
解决Grails中Book关联Chapter的N+1查询问题
你遇到的是典型的N+1查询问题:虽然给Chapter关联设置了lazy: false,但Book.findAll()默认还是会先查出所有Book,再逐个查询每个Book对应的Chapter,导致大量select * from chapter where book_id = ?的SQL。可以通过以下几种方式解决:
1. 使用HQL的join fetch一次性查询
直接在HQL里指定关联抓取,让数据库一次返回Book和对应的Chapter数据:
def books = Book.findAll("from Book b join fetch b.chapters")
这种方式会生成一条包含关联查询的SQL,一次性获取所有Book及其关联的Chapter,彻底避免N+1。
2. 通过Criteria查询设置FetchMode
用Grails的Criteria API,明确指定关联的抓取模式为JOIN:
def books = Book.createCriteria().list { fetchMode 'chapters', FetchMode.JOIN }
效果和HQL的join fetch一致,也是一次SQL完成所有数据的查询。
3. 确认mapping配置的正确性
检查Book类中的mapping配置是否正确定义,确保没有被其他配置覆盖:
class Book { static hasMany = [chapters: Chapter] static mapping = [ chapters: [lazy: false] ] }
不过要注意:即使设置了lazy: false,Grails默认的findAll()并不会自动做关联查询,还是会触发N+1,所以更推荐前两种主动指定抓取策略的方式。
内容的提问来源于stack exchange,提问作者user2572790
相关产品推荐
相关产品推荐

