基本问题:我与一个名为ProductOffering的查找实体之间存在许多关系(商店,产品)。在我有一个持久的StoreLocation并尝试附加临时产品的情况下,冬眠抱怨我什至不想保存。
问题:
我的域类如下所示:
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
我的看法是什么都没关系。可能是
hello
我收到以下错误。
错误500:not-null属性引用的是null或 transient 值:ProductOffering.product;嵌套的异常是org.hibernate.PropertyValueException:not-null属性引用的是null或 transient 值:ProductOffering.product
堆栈跟踪没有什么用:
org.springframework.dao.DataIntegrityViolationException:非null属性引用的是null或 transient 值
最佳答案
Grails围绕所有请求注册一个OpenSessionInView拦截器。这样可以确保在每个请求期间都打开一个Hibernate session ,并在请求结束时刷新并关闭该 session 。这样的好处是可以避免延迟加载异常。
由于 session 是在请求结束时刷新的,因此所有肮脏的持久性实例都会被推送到数据库中,这就是这里发生的情况。您加载storeLocation
实例并进行更改,以便刷新更改。您不需要保存ProductOffering
,因为在刷新storeLocation
时将以传递方式保存它,但是Product
实例不是,因此您将获得此异常。
如果您不想保留任何更改,则简单的解决方法是从持久性上下文中删除更改的实例-通过在render调用之前调用storeLocation.discard()
可以做到这一点。有关discard
方法的信息,请参见http://grails.org/doc/latest/ref/Domain%20Classes/discard.html。
关于hibernate - 呈现具有多对多关系的复杂表单时, hibernate 未保存的瞬时错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6673332/