在 grails 3 数据服务中查询与 JPA QL 的向后关联,对象上的 MissingMethodException executeQuery?

Querying backwards association with JPA QL in a grails 3 Data Service, MissingMethodException executeQuery on Object?

在收集作者及其书籍的数据库中,我们通过 Author 添加书籍作为 Book 个实例。

但是,Author 可能有尚未添加到数据库中的书籍。这就是为什么我们有一个外部理智计数器,告诉我们 Author 实际出版了多少本书。如果 numberOfKnownBooks 等于数据库中 Book 个实例的数量,那么我们认为我们有一个 Author 的完整参考书目。

一个SQL查询获取所有Authors其参考书目是完整的将这样写在SQL:

select author.id, count(*)
from book inner join author on book.author_id=author.id
group by author.number_Of_Known_Books, author.id
having count(*) = author.number_Of_Known_Books

这里的难点在于连接指向相反的方向,正常的示例通常显示如何创建一个查询来获得 BooksAuthors 的连接,而不是相反。

我在 Whosebug 中找到了一些文章,解释了如何在普通 JPQL 中做这样的事情(减去 group by ... 有复杂性)here,但是在 [=] 期望的 DSL 中这样做23=] 在 GORM 6.1+ 的数据服务中注释,我得到一个异常,发生在 AST 生成的代码的地牢中,说它无法在 java.lang.Object 上找到方法 executeQuery。这是一个合理的抱怨,但我不知道为什么会这样。不幸的是,无法逐步调试此代码。

这是我的数据服务:

import grails.gorm.services.Query
import grails.gorm.services.Service


@Service
abstract class AuthorService {

    @Query("""
            select a.*, count(a.id)
            from ${Book b} join ${b.author} a
            group by a.numberOfKnownBooks, a.id
            having count(*) = a.numberOfKnownBooks
""")
    abstract List<Author> retrieveCompleteAuthors()
}

更新:根据 jeff 的说明删除了无用的注释@GrailsCompileStatic 和@Transactional

完整解决方案,使用正确的 JPQL 查询:

@Service(Author)
abstract class AuthorService {
    @Query("""
        select auth from ${Author auth}  where auth.id in (
            select a.id
            from ${Book b} join ${b.author} a
            group by a.numberOfKnownBooks, a.id
            having count(*) = a.numberOfKnownBooks
        ) 
""")
    abstract List<Author> retrieveCompleteAuthors()
}

我预计这并不是您真正想要的 HQL,但这是一个单独的问题。如果您这样做,您询问的错误应该会消失...

import grails.gorm.services.Query
import grails.gorm.services.Service

@Service(Author)
abstract class AuthorService {

    @Query('''
            select a.*, count(a.id)
            from ${Book b} join ${b.author} a
            group by a.numberOfKnownBooks, a.id
            having count(*) = a.numberOfKnownBooks
    ''')
    abstract List<Author> retrieveCompleteAuthors()
}