Grails 2.5:复杂的“findOrCreate”和线程间同步(HTTP 会话)
Grails 2.5: Complex “findOrCreate” and synchronisation between threads (HTTP sessions)
在 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 中的服务函数 运行 完成后,数据才会持久化。这导致被同步块阻塞并在T1执行完服务方法之前进入的线程T2中标记为(A) returns null的查询。这导致了这样的结构:
D1/D2/D3
D1/D2/D4
而不是
D1/D2/D3
/D4
我的假设是,在 withNewTransaction
结束时的 (B) 中,数据将被持久化,然后并行会话,T2 中的 运行 将使用查询获取数据。
然而这并没有发生。
我错过了什么?
编辑:在开始时清除会话并在同步部分结束时刷新无效。
编辑 2:Hibernate 3.6 与 Grails 一起使用。这可能是问题的根源吗?
问题是查询中使用的属性之一在同步块之外被修改。否则逻辑工作正常。
在 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 中的服务函数 运行 完成后,数据才会持久化。这导致被同步块阻塞并在T1执行完服务方法之前进入的线程T2中标记为(A) returns null的查询。这导致了这样的结构:
D1/D2/D3
D1/D2/D4
而不是
D1/D2/D3
/D4
我的假设是,在 withNewTransaction
结束时的 (B) 中,数据将被持久化,然后并行会话,T2 中的 运行 将使用查询获取数据。
然而这并没有发生。
我错过了什么?
编辑:在开始时清除会话并在同步部分结束时刷新无效。
编辑 2:Hibernate 3.6 与 Grails 一起使用。这可能是问题的根源吗?
问题是查询中使用的属性之一在同步块之外被修改。否则逻辑工作正常。