0

I have to deal with cyclic dependent relations I cannot influence and I am fairly new to JPA.

So a Entity has members of the same Entity and I resolved that by:

@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;
}

When writing to the DB I have the problem that Hibernate seems to not know which A has to be persisted first. I tried to solve this by removing all relations from A, write to the DB and restore relations afterwards through hibernate.

This seems to work, but seems to fail if an A has no SubAs and this doesn't fit with my understanding of the issue. So I certainly be wrong somewhere.

The Entity without relations is persisted by an inner transaction:

@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();
    }
}

As a result I get a

ORA-02291: integrity constraint (...) violated - parent key not found

I can circumvent this issue by removing constraints from the DB, but this is not my preferred way of dealing with this.

sschrass
  • 7,014
  • 6
  • 43
  • 62

2 Answers2

0

I don't see any @Id attribute declared in class A. I believe you might have removed it for brevity.

Can you try updating @ManyToMany to @ManyToMany(cascade=CascadeType.ALL) as below and try.

@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;
}

Able to save it with below hibernate test code and should work with JPA as well.

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();

Incase I got your test scenario wrong, posting your basic test scenario would help.

0

Well, this was kind of mindbending for me, but my approach was okay with a slight mistake.

I had cyclic dependent Entities. Before writing to the DB took place I removed all relations from the entity, saved it to the DB and restored the relationships afterwards as an update. This was okay, because in this manner I had all entities in the DB and could restore the cyclic dependencies with ease. I wish I could have gotten rid of them in the first place, but no.

The mistake was in the how I did that. With having a single Transaction the removal of the relations had no effect, because when the Entity with all its relations got finally persisted to the DB I had restored the previous state already. I attempted to use a new Transaction with

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

but in the same Bean and how I learned the hard way the same transaction. The hint came from Strange behaviour with @Transactional(propagation=Propagation.REQUIRES_NEW)

So I injected a new instance of the same bean and executed the new Transaction on this instance, with access to the proxy and well --it worked.

Community
  • 1
  • 1
sschrass
  • 7,014
  • 6
  • 43
  • 62