当我试图将一个JSON有效负载绑定到一个对另一个域对象具有可空引用的现有域对象时,如果绑定的JSON表示引用为null,则绑定失败。这将导致持久性尝试在此错误中失败:
| Error 2011-12-21 10:21:24,202 ["http-bio-8080"-exec-3] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Message: null id in server.Uploader entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | update in server.SessionController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
| Error 2011-12-21 10:21:24,206 ["http-bio-8080"-exec-3] ERROR errors.GrailsExceptionResolver - AssertionFailure occurred when processing request: [POST] /Server/session/2
null id in server.Uploader entry (don't flush the Session after an exception occurs). Stacktrace follows:
Message: null id in server.Uploader entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | update in server.SessionController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread下面是有问题的域对象:
class Session {
DateTime dateCreated
DateTime lastUpdated
String ip
String state
static hasOne = [uploader:Uploader]
static constraints = {
ip blank: false
state blank: false
uploader nullable: true, unique: true
}
}
class Uploader {
DateTime dateCreated
DateTime lastUpdated
Session session
String firstName
String lastName
String organization
String phoneNumber
String emailAddress
static constraints = {
firstName blank: false
lastName blank: false
organization blank: false
}
}下面是抛出错误的控制器代码:
def update() {
def sessionInstance = Session.get(params.id)
if (!sessionInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'session.label', default: 'Session'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (sessionInstance.version > version) {
sessionInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'session.label', default: 'Session')] as Object[],
"Another user has updated this Session while you were editing")
render(view: "edit", model: [sessionInstance: sessionInstance])
return
}
}
sessionInstance.properties = params
if (!sessionInstance.save(flush: true)) { // <---- Error thrown here
render(view: "edit", model: [sessionInstance: sessionInstance])
return
}
flash.message = message(code: 'default.updated.message', args: [message(code: 'session.label', default: 'Session'), sessionInstance.id])
redirect(action: "show", id: sessionInstance.id)
}这是引起问题的JSON有效负载:
{
"id":2,
"dateCreated":"2011-12-21T09:33:33-06:00",
"ip":"127.0.0.1",
"lastUpdated":"2011-12-21T09:33:33-06:00",
"state":"closed",
"uploader":null
}但是这个JSON有效负载工作得很好:
{
"class": "server.Session",
"id":2,
"dateCreated":"2011-12-21T09:33:33-06:00",
"ip":"127.0.0.1",
"lastUpdated":"2011-12-21T09:33:33-06:00",
"state":"closed",
"uploader":null
}所发生的情况是会话的uploader属性被设置为"server.Uploader : null"。这是继.dump()之后的sessionInstance对象的sessionInstance.properties = params
<server.Session@713c6968 dateCreated=2011-12-21T09:33:33.000-06:00 lastUpdated=2011-12-21T09:33:33.000-06:00 ip=127.0.0.1 state=closed errors=grails.validation.ValidationErrors: 0 errors id=2 version=1 uploader=server.Uploader : null>当"class": "server.Session"属性在JSON有效负载中时,一切都正常工作,但是没有它,一切都会崩溃。我认为数据绑定能够处理这个问题,因为它可以很好地映射其余的属性,但是对于引用来说,它似乎失败了。
最后,我遇到这种情况的原因是,我正在尝试使用REST构建格里芬客户机,而且当HTTPBuilder将原始JSON响应转换为net.sf.json.JSONObject时,它似乎正在剥离"class": "server.Session",因为跨线响应中有属性,但是net.sf.json.JSONObject的转储没有,后续的JSON请求有效负载也没有。
G 224
更新
我还发现了一些额外的信息:
删除唯一约束的
uploader字段为非空,并且绑定的JSON对象试图将其设置为null,则属性不会更改(并且不会发生错误)。但是,如果"class": "server.Session"属性在绑定的JSON有效负载中,它将按预期更改为null .发布于 2011-12-21 18:12:52
IIRC的JSONObject将自动删除特殊属性,如"class“和"metaClass”(在POGO的情况下)。您可以通过JsonConfig实例来配置这种行为,但是我不知道HTTPBuilder是否允许您在适当的时候注入这样的实例。
另一种方法(类似于恶意)是以不同的名称(比如clazz)发送类属性值,Json不会删除这个名称。您必须在Grails侧注册一个过滤器,以便将'clazz‘映射到'class’中。
https://stackoverflow.com/questions/8593377
复制相似问题