Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have 2 tables.

//Accounts
@OneToMany(mappedBy="accounts", cascade=CascadeType.ALL)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Mails> mails;

//Mails
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="user_id" , referencedColumnName="id", insertable=false, updatable=false)
private Accounts accounts;

How to organize deleting all child rows when parent row will deleted? I'm tried to set CascadeType.DELETE_ORPHAN for Accounts table, but with that I can't to delete parent rows if childs is exists.

share|improve this question
Can you show the show create table MySQL output for both tables? – Marcell Fülöp 11 hours ago
@MarcellFülöp pastebin.com/N4y0LBmY – Eugene Mironenko 11 hours ago
The SQL syntax is correct and is in accordance with my answer, however I don't see the ON DELETE CASCADE in the foreign key definition which is explicitly required by the InnoDB engine on the table level to allow for automatic child deletions. – Marcell Fülöp 11 hours ago

3 Answers

up vote 0 down vote accepted

The problem probably is that the relation is defined in the wrong direction. Presuming that you have an account table with one-to-many relation to a mail table, you will end up not being able to delete a record from account until it has associated mail rows if you define the relation on account to reference mail. The correct way is to create the foreign key on mail to reference account.

With ON DELETE CASCADE, you tell MySQL that it should delete a row (whose table has the foreign key) if its parent (referenced by the key) is deleted. This operation is allowed by definition because in such a case the deleted record has references to it. In contrast, a deletion is not allowed if a record has references pointing to other records from it.

share|improve this answer
I forgot about ON DELETE CASCADE option. But now I can't to edit or remove parent rows. I'm tried to add foreign key manually and it works perfectly. ALTER TABLE Mails ADD FOREIGN KEY (user_id) REFERENCES Accounts(id) ON DELETE CASCADE ON UPDATE RESTRICT Where is error? – Eugene Mironenko 10 hours ago
Error code 1451, SQL state 23000: Cannot delete or update a parent row: a foreign key constraint fails – Eugene Mironenko 10 hours ago
With ON UPDATE RESTRICT MySQL disallows updating the referenced field (Accounts.id) if it has references to it. Like ON DELETE CASCADE allows deletion of Account rows (and automatically deletes rows from Mails referencing the deleted Account row), ON UPDATE CASCADE allows updating the id filed in an Account row that is referenced by one or more Mail rows (and it will update the referencing field, (Mail.user_id) as well). – Marcell Fülöp 3 hours ago
Yes. But How to set this parameters in hibernate? I added @OnDelete(action=OnDeleteAction.CASCADE) before OneToMany annotation, but it's not working. – Eugene Mironenko 2 hours ago
Sorry, I don't know Hibernate, but I'd assume the same way you did for ON DELETE? @OnUpdate(action=OnUpdateAction.CASCADE). This is just a guess, I really don't know Hibernate, was just trying to help you out the SQL level. – Marcell Fülöp 2 hours ago
show 3 more comments

The "mappedBy" property indicates that the other side owns the relationship, so in your case Mails owns the relationship which is probably not what you want.

JPA Cascades only work in one direction, from the owner of the relationship.

So if you want Mails to be deleted when deleting an Account, you need to switch the owner of the relationship:

//Accounts
@OneToMany(cascade=CascadeType.ALL)
private Set<Mails> mails;

//Mails
@ManyToOne(mappedBy="mails")
@JoinColumn(name="user_id" , referencedColumnName="id", insertable=false, updatable=false)
private Accounts accounts;
share|improve this answer
@ManyToOne(mappedBy="mails") It's not working. IDE say, that I can't to add mappedBy to ManyToOne annotation. – Eugene Mironenko 10 hours ago

You are using cascade=CascadeType.ALL in both entities. Try using that only at parent. This should work

//Accounts
@OneToMany(mappedBy="accounts", cascade=CascadeType.ALL,orphanRemoval=true)    
private Set<Mails> mails;

//Mails
 @ManyToOne
 @JoinColumn(name="user_id" , referencedColumnName="id" , nullable=false)
 private Accounts accounts;
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.