在Grails应用程序中,我们有一个接口,它接受一个类似路径的3级结构,可以从单个请求中的参数创建,如
level1/level2/document
对象level2
引用level1
和document
引用level2
。
可以并行上载使用相同level1 / level2子路径的多个对象,因此需要实现会话之间的同步。每个帐户都有自己的结构。
本质上,逻辑就像一个高级的findOrCreate,必须在多个并发请求之间进行同步。
我的想法是在服务方法中实现类似的东西:
Doc d
synchronised(currentUser) {
Dir.withNewTransaction {
Dir l1 = findFirstLevel(level1) // (A)
if (!l1) {
l1 = new Dir(name: level1)
l1.save()
}
Dir l2 = findSecondLevel(l1, level2)
if (!l2) {
l2 = new Dir(name: level2, parent: l1)
l2.save()
}
d = new Doc(name: docName, parent: l2)
d.save()
} // (B)
} // (C)
saveDocumentContent(d, content)
我使用withNewTransaction
来确保在同步部分结束之前保存记录,以确保仅为并行上传正确创建相同的结构一次。
但是,在线程T1中运行的服务功能完成之前,数据不会持久存在。这导致由(A)标记的查询在线程T2中返回null,该块被同步块阻塞并在T1完成执行服务方法之前输入。这导致了这样的结构:
D1/D2/D3
D1/D2/D4
而不是
D1/D2/D3
/D4
我的假设是,在withNewTransaction
末尾的(B)数据将被保留,然后在T2中运行的并行会话将使用查询获取数据。
然而,这不会发生。
我错过了什么?
编辑:在开始时清除会话并在同步部分结束时刷新无效。
编辑2 :Hibernate 3.6与Grails一起使用。这可能是问题的根源吗?