Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting from table with @OneToOne annotation

I'm using JPA2 and Hibernate implementation.

I've got simple mapping like this:

@Entity 
class Topic {

    @Id
    @GeneratedValue(strategy = IDENTITY)

    int id;

   @OneToOne(cascade = ALL)
   @JoinColumn(name = "id_poll")
   private Poll poll;

}

@Entity 
class Poll {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    int id;
}

Now, when I delete a Poll object which is also in Topic I get an error.

java.sql.SQLException: Integrity constraint violation FKCC42D924982D3F4B table: TOPICS in statement [delete from polls where id=?]

I understand that it is because I can't delete the Poll record if it has references in another table. How can I solve this problem? Do I have to manually set poll = null in a Topic table or is there a better solution?

like image 325
Dawid Avatar asked Jan 02 '11 22:01

Dawid


3 Answers

This is expected behavior:

A common problem with bi-directional relationships is the application updates one side of the relationship, but the other side does not get updated, and becomes out of sync. In JPA, as in Java in general it is the responsibility of the application, or the object model to maintain relationships.

Source: Object corruption, one side of the relationship is not updated after updating the other side

The correct place to handle this is in a @PreRemove callback:

@Entity 
class Poll {

    ...

    @PreRemove
    private void preRemove() {
        Poll poll = topic.getPoll();
        topic.setPoll( null );
    }
}

See also: Have JPA/Hibernate to replicate the “ON DELETE SET NULL” functionality

like image 72
Tomasz Avatar answered Sep 20 '22 15:09

Tomasz


I was not able to find a solution by now, so before I delete a Poll object I always get a Topic object which contains given Pool and set it to null.

Topic topic = entityManager.find( Topic.class, 1 );
Poll poll = topic.getPoll();
topic.setPoll( null );
entityManager.remove( poll );

And it works correctly.

like image 40
Dawid Avatar answered Sep 20 '22 15:09

Dawid


It looks like the @OneToOne annotation in JPA 2 contains an orphanRemoval flag, you could try setting that and see if it removes it gracefully.

like image 45
digitaljoel Avatar answered Sep 22 '22 15:09

digitaljoel