【问题标题】:Hibernate unsaved transient errors when rendering a complex form with a many-to-many relationship渲染具有多对多关系的复杂表单时休眠未保存的瞬态错误
【发布时间】:2011-10-04 03:20:01
【问题描述】:

基本问题:我有一个名为 ProductOffering 的查找实体的多对多关系(商店、产品)。在我有一个持久的 StoreLocation 并尝试附加瞬态产品的情况下,即使我不想保存,休眠也会抱怨。

问题:

  1. 为什么 grails/gorm/Hibernate 试图保存我的实体?
  2. 有没有更好的方法来解决这个问题?

我的域类如下所示:

class StoreLocation {
    String name
    List offerings
    static hasMany = [offerings:ProductOffering]
    static constraints = {
    }
}

class Product {
    String name
    static hasMany = [offeredBy:ProductOffering]
    static constraints = {
        name(unique:true)
        offeredBy(nullable:true)
    }
}

class ProductOffering {
    static belongsTo = [product:Product, store:StoreLocation]
    static constraints = {
    }
}

我的 StoreLocationController “编辑”操作如下所示。

def edit = {
    //get the store we want to edit
    def storeLocation = StoreLocation.get(params.id)
    //create a transient product and add it to the store
    // by attaching it to a transient productOffering
    def product = new Product()
    def offering = new ProductOffering()
    offering.product = product
    storeLocation.addToOfferings(offering)
    //render the edit page
    render(view:"edit", model:[storeLocation:storeLocation])
}

假设我有一个 ID=1 的 storeLocation。我去编辑 StoreLocation 本地主机:8080/myapp/storeLocation/edit/1

我的观点是什么样的并不重要。可能是<p>hello</p>

我收到以下错误。

错误 500:非空属性引用空值或瞬态值:ProductOffering.product;嵌套异常是 org.hibernate.PropertyValueException:非空属性引用空值或瞬态值:ProductOffering.product

堆栈跟踪并没有多大用处:

org.springframework.dao.DataIntegrityViolationException:非空属性引用空值或瞬态值

【问题讨论】:

    标签: hibernate grails grails-orm


    【解决方案1】:

    Grails 为所有请求注册一个 OpenSessionInView 拦截器。这确保了 Hibernate 会话在每个请求期间都是打开的,并且会话在请求结束时被刷新和关闭。这样做的好处是可以避免延迟加载异常。

    由于会话在请求结束时被刷新,任何脏的持久实例都会被推送到数据库中,这就是这里发生的事情。您加载 storeLocation 实例并对其进行更改,以便刷新更改。您不需要保存ProductOffering,因为当storeLocation 被刷新时,它会被传递保存,但Product 实例不是,所以你会得到这个异常。

    如果您不希望任何更改被持久化,简单的解决方法是从持久化上下文中删除更改的实例 - 通过在渲染调用之前调用 storeLocation.discard() 来做到这一点。有关discard 方法的信息,请参阅http://grails.org/doc/latest/ref/Domain%20Classes/discard.html

    【讨论】:

    • 完美,谢谢。只要我确保在从持久性上下文中丢弃 StoreLocation 之前加载我所有的子关系,我就应该很好。你能以不同的方式处理它吗?我可以告诉 grails/spring/hibernate 在会话结束时不要隐式刷新吗?如果我设置 flush.mode=NEVER 会发生什么?
    猜你喜欢
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多