在收集作者及其书籍的数据库中,我们将书籍添加Author
为Book
实例。
但是,Author
可能有尚未添加到数据库的书籍。Author
这就是为什么我们有一个外部理智计数器,告诉我们一个人实际出版了多少本书。如果numberOfKnownBooks
等于Book
数据库中的实例数,那么我们认为我们有一个Author
完整的参考书目。
获取所有Authors
参考书目完整的 SQL 查询将在 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
这里的困难在于连接指向相反的方向,并且正常示例通常显示如何创建查询以获取Books
与 连接Authors
,而不是相反。
我在 stackoverflow 中找到了一些文章,解释了如何在普通 JPQL 中执行类似的操作(减去 group by ... 有复杂性),@Query
但是在 GORM 6.1+ 中的数据服务中的注释所期望的 DSL 中执行此操作,我得到一个异常,发生在 AST 生成的代码的地牢中,说它executeQuery
在java.lang.Object
. 这是一个合理的投诉,但我不知道为什么会这样。不幸的是,无法逐步调试此代码。
这是我的数据服务:
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()
}