Stefania
Stefania

Reputation: 683

JPA: relation manyToMany on the same entity

I have an Entity that has two relation manyToMany with itself and I don't want to use Cascade.MERGE because I need to do some data checks to validate the data:

@Entity("device")
public class Device {
...
@ManyToMany(mappedBy = "parents", targetEntity = Device.class, fetch = FetchType.LAZY)
    public Set<Device> getChildren() {
        return this.children;
    }

    @Override
    @ManyToMany(targetEntity = Device.class, fetch = FetchType.LAZY)
    @JoinTable(name = "dem_hierarchy", joinColumns = {
        @JoinColumn(name = "CHILDREN_UUID", referencedColumnName = "UUID")},
            inverseJoinColumns = {
                @JoinColumn(name = "DEM_DEVICE_UUID", referencedColumnName = "UUID")})
    public Set<Device> getParents() {
        return parents;
    }

...
}

When I save a tree like this:

Device grandGrandPa = new Device();
grandGrandPa.setName("TEST" + counter + "_grandGrandPa");

Device grandPa = new Device();
grandPa.setName("TEST" + counter + "_grandPa");

grandGrandPa.addChild(grandPa);

Device daddy = new Device();
daddy.setName("TEST" + counter + "_daddy");

grandPa.addChild(daddy);

Device son = new Device();
son.setName("TEST" + counter + "_son");

daddy.addChild(son);
grandGrandPa = deviceService.register(grandGrandPa);

The register method is recursive and it descends the tree using the children column. When its the turn of the "grandPa" to be saved the weblogic return an exception:

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing

I cannot understand why this happens. It gives me this error when in code there are some queries on parent Device: first turn it is empty, second turn it has one value. I'm using weblogic 12.1.3 and hibernate 4.0.0, as database Oracle 11g.

Upvotes: 0

Views: 1356

Answers (1)

crizzis
crizzis

Reputation: 10726

It gives me this error when in code there are some queries on parent Device

By default, Hibernate will flush pending changes to the database before attempting to execute a query. At that stage, all entities referenced in all relationships should have been persisted, or else an exception will be thrown.

Also, since mappedBy is declared on the children end, the parents is the owning side of the relationship. Because of that, Hibernate will ignore children completely at persist time and look for transient entities in parents instead. Your persisting logic should therefore be reversed - save parents first, children last (alternatively, you could simply declare children the owning side).

Upvotes: 1

Related Questions