我正在阅读维基百科上的对象池模式(http://en.wikipedia.org/wiki/Object_pool),它提到了"危险的陈旧状态".
什么是"陈旧"状态?我知道状态是变量/数据,例如我的字段和属性,但它陈旧或危险陈旧是什么意思?
我在使用hibernate的基于spring框架的Web应用程序的控制器中获得此异常.我已经尝试了很多方法来解决这个问题,但无法解决它.
在控制器的方法中,handleRequestInternal对数据库的调用主要是为了"读取",除非它是一个提交动作.我一直在使用,Spring的Session但是转移到getHibernateTemplate()了,问题仍然存在.
基本上,这对数据库的第二次调用会抛出此异常.那是:
1)getEquipmentsByNumber(number) {首先,基于'number'从DB获取设备,其具有属性列表,并且每个属性具有值列表.我循环遍历这些值(原始对象字符串)以读入变量)
2)getMaterialById(id){基于id获取材料}
我确实理解第二次调用很可能是使会话"刷新",但我只是"读取"对象,那么为什么第二次调用会在Equipment属性上抛出过时的对象状态异常,如果没有任何改变的话?
我无法在调用后清除缓存,因为它会导致我传递给视图的对象上的LazyExceptions.
我读过这个:https: //forums.hibernate.org/viewtopic.php?f = 1&t = 99635&start = 0 但根据提供的建议无法解决问题.
我该如何解决这个问题?任何想法和想法都表示赞赏.
更新:
我刚刚测试的是,在getEquipmentsByNumber()从属性列表中读取变量后的函数中,我这样做:getHibernateTemplate().flush();现在异常就在这一行而不是调用fetch材料(即getMaterialById(id)).
更新: 在显式调用flush之前,我从会话缓存中删除对象,以便缓存中没有过时的对象.
getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();
Run Code Online (Sandbox Code Playgroud)
好的,现在问题已经转移到我执行此操作后从DB中的下一次提取.我想我必须将方法标记为已同步,并在我阅读完内容后立即逐出对象!听起来不太好.
更新:
使handleRequestInternal方法"同步".错误消失了.当然,不是最好的解决方案,而是做什么!试图handleRequestInternal关闭当前会话并打开一个新会话.但它会导致应用程序的其他部分无法正常工作.试图使用ThreadLocal那也不起作用.
控制器逻辑:
def updateObject() {
Object o = Object.get(params.id as Long)
o.otherObjects.clear()
objectDataService.saveObject(o.id)
OtherObject newObject = new OtherObject;
o.addToOtherObjects(newObject)
objectDataService.saveObject(o.id)
}
Run Code Online (Sandbox Code Playgroud)
ServiceLogic
def saveObject(long profileId) {
o.save(flush:true)
}
Run Code Online (Sandbox Code Playgroud)
怎么了
在90%的情况下,这将起作用.
问题
ERROR errors.GrailsExceptionResolver - StaleObjectStateException occurred when processing request: [GET] /controller/updateObject - parameters:
stuff[]: data
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1].
Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]
Run Code Online (Sandbox Code Playgroud)
我已阅读相关问题并找到merge您在上面看到的电话.它解决了大约50%的案例,但并非全部.
我们正在尝试在抛出StaleObjectStateException之后组合对象以保存合并副本.
这是我们的环境状况:
使用案例:
我们希望优雅地处理异常.由于用户共享父级的所有权,因此用户1应该能够成功保存,并使用他的新孩子和用户2的孩子保存父级.
根据Ayende(http://msdn.microsoft.com/en-us/magazine/ee819139.aspx),当SOSE被抛出时:
您的会话及其加载的实体是toast,因为使用NHibernate时,会话抛出的异常会将该会话移动到未定义状态.您无法再使用该会话或任何已加载的实体
已经为现在没有用的会话分配了一个ID和版本号.(我希望它没有.)
我们如何结合使用ISession.Merge()和ISession.Refresh()来获得一个同时具有C1和C2的新保存的Parent?
我们已经尝试了许多奥术排列,其中没有一个完全奏效.通常,"行已被另一个事务更新或删除(或未保存的值映射不正确")或ODBC级别的实际ID冲突.
我们的理论,目前:
但是,所有文档都表明newSession.Merge 应该足够了.
用作研究的其他帖子:
Fluent NHibernate Newbie:Row被另一个事务更新或删除
是否有使用乐观锁定时不会抛出的ISession.Merge()的替代方法?
StaleObjectstateException行已更新或删除
如何告诉NHibernate只保存已更改的属性
Hibernate(JPA):如何在修改和提交多个对象时处理StaleObjectStateException(java,但相关,我认为)
nhibernate fluent-nhibernate optimistic-locking staleobjectstate
根据"Book of Geb",我开始绘制门户网站的网页.我更喜欢使用静态内容闭包块中定义的变量,然后在页面方法中访问它们:
static content = {
buttonSend { $("input", type: "submit", nicetitle: "Senden") }
}
def sendLetter() {
waitFor { buttonSend.isDisplayed() }
buttonSend.click()
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,有时候我会得到Geb等待超时异常(60秒后),甚至更糟糕的是我收到了众所周知的"StaleElementReferenceException".
使用"isEnabled"代替"isDisplayed"时可以避免等待超时,但对于"StaleElementReferenceException",我只能应用以下解决方案:
def sendLetter() {
waitFor { buttonSend.isEnabled() }
try {
buttonSend.click()
} catch (StaleElementReferenceException e) {
log.info(e.getMessage())
buttonSend.click()
}
}
Run Code Online (Sandbox Code Playgroud)
我想,这个解决方案并不是很好,但我无法应用另一篇文章中描述的明确等待.因此,我有一些一般性的问题:
我希望每一个有助于理解或解决这个问题的提示.最好的方法是拥有一个简单的代码示例,因为我还是初学者.谢谢!
hibernate ×2
exception ×1
geb ×1
grails ×1
grails-orm ×1
groovy ×1
java ×1
nhibernate ×1
spring ×1