保存错误组合的EntityNotFoundException

时间:2017-07-27 16:47:51

标签: java spring hibernate jpa spring-data-jpa

我发现了一些我无法理解的奇怪的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

然后失败了!所以,问题是:

  1. 为什么Hibernate会在节省一些东西的同时加载某些内容? :)
  2. 解决此问题的最佳方法是什么?

0 个答案:

没有答案