基本问题:我与一个名为ProductOffering的查找实体有很多关系(商店,产品)。在我有一个持久的StoreLocation并试图附加瞬态产品的情况下,hibernate抱怨即使我不想保存它。
问题:
我的域类看起来像这样:
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 /编辑/ 1
我的观点看起来并不重要。它可以是
hello
我收到以下错误。
错误500:not-null属性引用null或transient值:ProductOffering.product;嵌套异常是org.hibernate.PropertyValueException:not-null属性引用null或transient值:ProductOffering.product
堆栈跟踪没有多大帮助:
org.springframework.dao.DataIntegrityViolationException:not-null属性引用空值或瞬态值
答案 0 :(得分:3)
Grails在所有请求周围注册一个OpenSessionInView拦截器。这可确保Hibernate会话在每个请求的持续时间内打开,并在请求结束时刷新和关闭会话。这样可以避免延迟加载异常。
由于会话在请求结束时被刷新,因此任何脏持久化实例都会被推送到数据库,这就是这里发生的事情。您加载storeLocation
实例并进行更改,以便刷新更改。您不需要保存ProductOffering
,因为在storeLocation
被刷新时会传递保存,但Product
实例不会,因此您会收到此异常。
如果您不希望保留任何更改,那么简单修复就是从持久化上下文中删除已更改的实例 - 通过在呈现调用之前调用storeLocation.discard()
来执行此操作。有关discard
方法的信息,请参阅http://grails.org/doc/latest/ref/Domain%20Classes/discard.html。