0

我离开 Grails 有一段时间了,所以我尝试创建具有一些基本域关系(一对多、多对多)的演示 rest-api 应用程序并遇到了一些奇怪的问题。简而言之,我有 4 个域类,如下所示:

class Publisher {
    String name
    static hasMany = [books:Book]
}

class Author {
    String name
    static hasMany = [books: Book]    
}

class Category {
    String name
    static belongsTo = Book
    static hasMany = [books:Book]
}

class Book {
    String title
    Publisher publisher    
    static hasMany = [categories: Category]
}

我正在尝试在 bootrap.groovy 中插入一些演示数据(使用多种不同的方法),但是应该进入联合表的数据不会持久化(空)。例如,即使使用 cascade-create,'edge' 记录也会被持久化(例如从 boook 创建的类别),但是它们之间的连接表中没有数据):

在此处输入图像描述

Bootstrap.groovy 使用不同的方法插入记录:

// Stand-alone category
def science = new Category(name: 'science').save(failOnError: true)        

// publishers
def manning = new Publisher(name: 'manning').save(failOnError: true)
def amazon =   new Publisher(name: 'amazon').save(failOnError: true)


// Create single author 
def johnDoe = new Author(name: 'John Doe').save(failOnError: true)

// Create-cascade from Author-Book-Category with explicid 'new' and 'save' Book
def jackDanields = new Author(name: 'Jack Daniels')
    .addToBooks(new Book(title: 'Hate book', publisher: manning).addToCategories(name: 'love').save())
    .addToBooks(new Book(title: 'Fiction book', publisher: manning).addToCategories(name: 'fiction').save())
    .save(failOnError: true)


// Create-cascade from Author-Book without explicit save of book
def zoran = new Author(name: 'Zoran')
    .addToBooks(title: 'First book', publisher: manning)
    .addToBooks(title: 'Second book', publisher: manning)
    .addToBooks(title: 'Third book', publisher: manning)
    .save(failOnError: true)

我尝试了 H2 和 MariaDb,结果是一样的。github 上提供了完整的项目:https ://github.com/zbubric/grails4-rest-sample

那么,我错过了什么或者它是一些已知的问题/功能?

4

2 回答 2

1

zbubric

回答你的问题

那么,我错过了什么或者它是一些已知的问题/功能?

我完全同意 Olav 的评论,即您需要将所有插入包装BootStrap.groovy到新事务中以解决问题。

让我解释一下为什么事务可以在连接表中保存数据。

默认情况BootStrap.groovy下,有一个打开的休眠会话(使用 COMMIT 刷新模式),但没有活动的休眠事务。

COMMIT 刷新模式在这里很重要,因为在这种模式下,会话的刷新仅在事务提交时完成。但是在您的情况下,之后不会进行会话刷新,因为BootStrap.groovy我之前很伤心,因为没有活动的事务。并且没有会话刷新意味着不保存由级联添加的实体关联(还使用数据库事务中的原始 sql 查询在实践中检查了它 - 仅在会话刷新后才在连接表中具有数据)。

要检查是否有会话BootStrap.groovy(并获取有关它的更多详细信息),您可以参考

Holders.applicationContext.getBean("sessionFactory").getCurrentSession()

在你的代码中。

要检查是否存在活动事务,BootStrap.groovy您可以添加flush: true到任何save方法调用。

例如:

def science = new Category(name: 'science').save(failOnError: true, flush: true)

在这种情况下,您应该得到一个例外:

javax.persistence.TransactionRequiredException: no transaction is in progress

它的行为是这样的,因为默认情况下,在 grails 4.0.0 中,会话被配置为不允许在没有活动事务的情况下进行刷新。

于 2019-09-12T12:32:29.967 回答
0

我相信您的类别>书籍关系也错误。

书籍有一个类别 类别可以有一个或许多书籍

因此 Book 可以有一个“Category cat”字段或“belongsTo”;belongsTo 不应与“hasMany”在同一个地方

于 2021-02-26T18:23:30.913 回答