持久的循环依赖实体

时间:2016-01-25 14:48:25

标签: oracle hibernate jpa

我必须处理我无法影响的循环依赖关系,而且我对JPA还不熟悉。

因此,实体拥有相同实体的成员,我通过以下方式解决了这个问题:

@Entity
@Table("A")
public class A {
    @ManyToMany
    @JoinTable(name = "A_HAS_SUBAS",
        joinColumns = {@JoinColumn(name = "A_ID")},
        inverseJoinColumns = {@JoinColumn(name = "SUBA_ID")})
    private Set<A> as;
}

写入数据库时​​,我遇到的问题是Hibernate似乎不知道哪个A必须先保留。我尝试通过从A中删除所有关系,写入数据库并在之后通过休眠恢复关系来解决这个问题。

这似乎有效,但如果A没有SubAs,这似乎会失败,而这与我对该问题的理解不相符。所以我在某个地方肯定是错的。

没有关系的实体由内部事务持久化:

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
private void immediatelySaveNewEntity(A entity) {
    try {
        if (!dao.entityExistsFromId((int) entity.getId())) { dao.save(entity); }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

结果我得到了一个

  

ORA-02291:违反了完整性约束(...) - 未找到父密钥

我可以通过删除数据库中的约束来绕过这个问题,但这不是我处理此问题的首选方法。

2 个答案:

答案 0 :(得分:0)

我没有在类@Id中声明任何A属性。我相信你可能为了简洁而删除了它。

您可以尝试将@ManyToMany更新为@ManyToMany(cascade=CascadeType.ALL),如下所示,然后尝试。

@Entity
@Table("A")
public class A {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "A_HAS_SUBAS",
          joinColumns = {@JoinColumn(name = "A_ID")},
          inverseJoinColumns = {@JoinColumn(name = "SUBA_ID")})
    public Set<A> as;
}

能够使用以下hibernate测试代码保存它,并且也可以使用JPA。

Session sess = //Get Session
Transaction tx1 = sess.beginTransaction();

A a = new A();
a.as = new HashSet<>();
a.as.add(new A());
a.as.add(new A());
sess.persist(a);
tx1.commit();

如果我的测试场景错误,发布基本测试场景会有所帮助。

答案 1 :(得分:0)

嗯,这对我来说很有意思,但我的做法还是稍有不妥。

我有循环依赖实体。在写入数据库之前,我删除了实体中的所有关系,将其保存到数据库,然后将更新后的关系恢复。这没关系,因为通过这种方式,我拥有了DB中的所有实体,并且可以轻松地恢复循环依赖关系。 我希望我可以在第一时间摆脱它们,但不是。

错误在我是如何那样做的。通过单个事务,删除关系没有任何效果,因为当具有所有关系的实体最终持久保存到DB时,我已经恢复了之前的状态。 我试图使用新的交易

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)

但是在同一个Bean中我是如何通过同样的事务学习的。 提示来自Strange behaviour with @Transactional(propagation=Propagation.REQUIRES_NEW)

所以我注入了同一个bean的一个新实例,并在这个实例上执行了新的Transaction,可以访问代理,而且工作正常。