以下是两种类型的部分,
public class Address {
Set<Employee>employees=new HashSet<Employee>();
public class Employee {
private Address address;;
例如,员工在地址上工作。它们对Hibernate的映射是(部分),
<class name="Address">
<cache usage="read-write"/>
<set name="employees" inverse="false">
<cache usage="read-write"/>
<key column="address_" not-null="true"/>
<one-to-many class="Employee"/>
</set>
</class>
<class name="Employee" >
<cache usage="read-write"/>
<many-to-one name="address" column="address_" not-null="true" insert="false" update="false"/>
所以我们有一个双向的一对多关联。关联的持久性由收集方确定,而不是由员工中的Address引用确定。为了检查这一点,我故意向两位员工添加地址引用。当两个员工都坚持到数据库时,我确实看到了这种情况。但是这两个地址引用被持久化到第二层高速缓存,这是我不理解的。
Employee employee=new Employee(1l,"Foo1",1.00);
Employee employee2=new Employee(2l,"Foo2",2.00);
Address address=new Address(12l,"foostreet", "12 foo", "FooCity12");
Address address3=new Address(34l,"foostreet", "34 foo", "FooCity34");
address.getEmployees().add(employee);
address.getEmployees().add(employee2);
employee.setAddress(address3);
employee2.setAddress(address3);
session.save(address);
session.save(address3);
session.save(employee);
session.save(employee2);
tx.commit();
然后在新的会话中,
employee= (Employee) session.get(Employee.class, 1l)l
address=employee.getAddress();
employee= (Employee) session.get(Employee.class, 2l);
address=employee.getAddress();
没有Ehcache地址是(代理)地址#12l,所以员工所属的集合的容器,地址#12l。但是Ehcache的地址是地址#34l的aproxy,所以我们故意设置了地址的引用。
我不知道这是怎么回事,因为
BackrefPropertyAccessor$BackrefSetter.set(Object, Object, SessionFactoryImplementor){
}
答案 0 :(得分:0)
问题在于你不保持关系的双向性,而是依靠Hibernate(以及数据库的底层关系模型)为你“修复”它。一旦使用有状态的OO表示,问题就会暴露出来。您很可能已经仅使用Session
观察它。
基本上发生的事情是你只更新关系的“拥有”方面,而不是两者。鉴于底层数据库是关系型的,因此只在一端持有“FK”,当您从该模型重新加载时,问题就会消失。
您需要做的是更新关系的两端,即employee.setAddress()
AND address.addEmployee()
(而不是将原始Set<Employee>
暴露给用户) 。此外,如果员工已经与另一个地址相关联,那么它也需要从该集合中移除......这就是OO非常方便的地方:因为这个逻辑实际上应该是.setAddress()
的一部分或者模型上的.addEmployee()
方法,用于检查是否有任何要清理的内容,并回调到另一端,将该逻辑整齐地封装在Address
或{{1}的消费者之外} class。