我发现了一些我无法理解的奇怪的Hibernate行为。
我们说我上课 A (受到这个问题的启发JPA: How to have one-to-many relation of the same Entity type)
@Entity
public class A {
@Id
private String id;
private String name;
@ManyToOne
@JoinColumn(name = "PARENT")
private A parent;
@OneToMany(mappedBy = "parent",cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
private Set<A> children;
// Getters, Setters, etc...
}
另外,假设我们有Spring JPA Repository
public interface ARepository extends JpaRepository<A, Long> {}
魔法发生的测试课
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:spring/applicationContext-test.xml" })
public class ATest {
@Autowired
private ARepository aRepository;
@Test
public void testA() {
A parent = new A();
parent.setName("I am Parent: 121_1001_21");
parent.setId("121_1001_21");
A son = new A();
son.setName("I am Son: 121_1001_31");
son.setId("121_1001_31");
son.setParent(parent);
A daughter = new A();
daughter.setName("I am Daughter: 121_1001_32");
daughter.setId("121_1001_32");
daughter.setParent(son);
// daughter.setParent(parent);// yes, I'm intentionally creates wrong hierarchy
parent.setChildren(new HashSet<>(Arrays.asList(daughter, son)));// order of elements in set matters!
son.setChildren(new HashSet<>(Arrays.asList(daughter)));
aRepository.save(parent);
}
}
所以层次结构如下:
Parent (121_1001_21)
Son (121_1001_31)
Daughter (121_1001_32)
Daughter (121_1001_32)
但是这个测试在使用
保存实体时失败了javax.persistence.EntityNotFoundException:
Unable to find com.orga.pcom.om.core.entity.productorder.A with id 121_1001_31
经过数小时的调试后,我发现Hibernates尝试加载链接的实体并以这种方式加载它:
Parent (121_1001_21) 1st load
Son (121_1001_31) 3rd load (this entity loading is fail!)
Daughter (121_1001_32) 2nd load
Daughter (121_1001_32) 2nd load
然后失败了!所以,问题是: