因此,在批量数据加载期间,我正在构建一个庞大的域对象树,检查内部一致性,在它们之间创建引用......大量处理。然后在保存时,我通过调用session.clear()每20条记录来批量保存。
我的问题是被引用的域对象在清除时会从会话中分离出来,所以当我尝试级联保存时,我得到了预期的一个具有相同标识符值的不同对象已经与会话相关联< / strong>
域模型的片段(级联设置在任何类中都不明确):
class School {
String name
}
class Room {
String roomNum
School school
static belongsTo = School
static hasMany = [teachers:Teacher]
}
class Teacher {
String name
Room room
School school
static belongsTo = Teacher
static hasMany = [students:Stuent]
}
class Student {
String name
Teacher teacher
School school
static belongsTo = Student
}
还有一些层,每层的宽度更多,每个域都带有“学校”的引用,以便于搜索。在服务中,这些对象都是通过对持久学校的引用构建的。
def buildData() {
School s = School.get(1)
Room r = new Room(name: "A", school: s)
Teacher t = new Teacher(room: r, school: s, name: "Smith")
r.addToTeachers(t)
Student s = new Student(teacher: t, school: s, name: "Billy")
t.addToStudents(s)
//ad nauseum
}
def persistData() {
//lots of processing
def session = sessionFactory.currentSession
session.flush()
session.clear()
........
r.save(failOnError:true)
}
r.save()失败,非唯一ID为1,我可以检查r.school.isAttached()并且它是假的。所以我把它改成......
...
session.clear()
r.school = School.get(r.school.id)
log.info("Attached now? ${r.school.isAttached()}") //shows true
r.save(failOnError:true)
}
r.save()再次失败,可以预见,r.teacher [0] .school.isAttached()是假的......
我是否必须手动移动这个荒谬的树并重置每个子对象对刷新的“school”对象的引用?我觉得我一定是错过了什么或做了一些疯狂的事情。
答案 0 :(得分:2)
像往常一样,我踩得足够,看向正确的位置,我通常会把它搞清楚。
更换
r.school = School.get(r.school.id)
与
r.school.attach()
通过重新附加内存引用而不是加载新引用并将r.school实例设置为其他实例来解决此问题。确认这是通过调试和查看对象编号发生的。
我以为我过去曾经这样做过,并且在加入会议时遇到了问题,但我一定是弄错了。
答案 1 :(得分:0)
附加作品。 get是特殊的,因为它首先在本地查找以避免数据库命中vs load(见下文):
Hibernate: Difference between session.get and session.load
此外,findById始终有效。