Mrvonwyl
Mrvonwyl

Reputation: 347

Entity Mapping with Cascade does not seem to work

I have the following Situation:

OrganisationEntity.java

@Entity
@Table(name = "organisation")
public class OrganisationEntity {
    // ...
    private PersonEntity contactPerson;
    // ...    
    @OneToOne
    @JoinColumn(name = "contact_person_id", referencedColumnName = "id", nullable = false)
    public PersonEntity getContactPerson() {
        return contactPerson;
    }

    public void setContactPerson(PersonEntity contactPerson) {
        this.contactPerson = contactPerson;
    }
    // ...
}

ContactPerson.java

@Entity
@Table(name = "person")
public class PersonEntity {
    private int id;
    // ...
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    // ...
}

On the database the table Organisation has a non-nullable foreign key to Person. The entity mapping is uni-directional New when I want the persist a new pair of records (one organisation and one person) with merge on the OrganisationEntity I get the following error:

17:10:19.827 WARN [http-nio-8080-exec-2] [org.hibernate.action.internal.UnresolvedEntityInsertActions] [144] HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.

Unsaved transient entity: ([ch.freiwilligenarbeit_sempach.entity.PersonEntity#0])

Dependent entities: ([[ch.freiwilligenarbeit_sempach.entity.OrganisationEntity#]])

Non-nullable association(s): ([ch.freiwilligenarbeit_sempach.entity.OrganisationEntity.contactPerson])

This makes perfect sense to me, since it tries to insert the organisation with no reference to the person whatsoever. So I would usually define a cascade behaviour, so that hibernate inserts the person first, sets the reference ond the organisation and then persists the organisation. I tried the following on the organisation entity:

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "contact_person_id", referencedColumnName = "id", nullable = false)
public PersonEntity getContactPerson() {
    return contactPerson;
}

and

@OneToOne
@JoinColumn(name = "contact_person_id", referencedColumnName = "id", nullable = false)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
public PersonEntity getContactPerson() {
    return contactPerson;
}

But neither of the seem to work. I still get the same error. But I think this should actually work.

Any help is highly appreciated! Thanks in advance.

Upvotes: 1

Views: 1813

Answers (2)

Mrvonwyl
Mrvonwyl

Reputation: 347

This did the trick.

@Cascade(org.hibernate.annotations.CascadeType.ALL)

Although I believe I stopped tomcat and cleaned redeployed the webapp i did not work yesterday. Today it worked as expected, so that the referenced entities (Person) were inserted before the referencing entity (Organisation).

Upvotes: 1

lord_hokage
lord_hokage

Reputation: 187

I don't understand completely, what do you want, but I suppose that you want to save a person entity with a person organization. If you use different ids, you should add the @OneToOne annotation with attribute mappedBy=contactPerson

In the PersonEntity class

@OneToOne(cascade = CascadeType.ALL, mappedBy = "contactPerson")
private OrganisationEntity orgEntity;

In the OrganisationEntity class

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "contact_person_id", nullable = false)
private PersonEntity contactPerson; // name which is pointed as mappedBy attribute

Then you can save this correct writing something like this

orgEntity.setContactPerson(contactPerson);
orgRepo.save(orgEntity);

p.s. I wrote using field injection, but it's not necessary.

Upvotes: 1

Related Questions