4

Edit: Modifying the question to better reflect the problem. Originally posted question here

I have a parent (Context) and a child (User) entity (ManyToOne relationship). Cascade 'REMOVE' on the parent is not deleting the child. Code as below:

//Owning side - child
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column(name = DBColumns.USER_NAME)
    private String name;
    @ManyToOne
    @JoinColumn(name = DBColumns.CONTEXT_ID)
    private Context context;
}

//parent
@Entity
public class Context {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column(name = DBColumns.CONTEXT_NAME)
    private String name;
    @OneToMany(mappedBy = "context", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
    private Set<User> users = new HashSet<User>();
}

//usage
Context sampleContext = new Context("sampleContext");
em.persist(sampleContext);
User sampleUser = new User(sampleContext, "sampleUser");
em.persist(sampleUser);
em.remove(sampleContext); //should remove user as well but throws foreign key dependency error
Neo
  • 3,465
  • 5
  • 26
  • 37
  • By the way. If you specify orphanRemoval=true there is no need to add CascadeType.REMOVE. (see JSR338, section 2.9) – 8hZWKA Oct 08 '16 at 10:54

3 Answers3

3

I needed to refresh the entity before removing it:

em.refresh(sampleContext);
em.remove(sampleContext);

Earlier, the entity being deleted (sampleContext) did not know that sampleUser is associated with it (probably because sampleContext was being fetched from cache). Doing a refresh before delete ensures that the entity is updated from the database.

Neo
  • 3,465
  • 5
  • 26
  • 37
1

You are calling remove() on sampleUser not sampleContext, and User does not cascade remove to Context, so you should only see the User being deleted.

If you call remove() on sampleContext, you must also ensure that when you created the User you added the User to the Context's users. You are most likely only setting the User's conext.

James
  • 17,965
  • 11
  • 91
  • 146
  • Corrected typo. It had to be `remove(sampleContext)`. – Neo Apr 12 '13 at 07:11
  • This solution works. However, it is not necessary to manually add `User` to `Context`'s users. JPA does it by itself. I only needed to refresh the `Context` and then remove it (so that its `User`s are now updated from the database) – Neo Apr 12 '13 at 07:15
0

Don't map your relation table as en entity. Use @ManyToMany Instead and make your user entity owner of the relationship.

Edit :

So your association table primary key must be composed of both foreign key.

See this http://giannigar.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/

Gab
  • 7,869
  • 4
  • 37
  • 68
  • I want to keep it separate so that at a later point of time, I can specify the mapping using strings instead of direct entities (to facilitate regular expressions). For example, I would want to say "All `users` belong to `employee` role" by the mapping `user:role :: *:employee`. – Neo Apr 10 '13 at 05:36
  • Thanks for the link. It was informative. However, I am having the problem with ManyToOne relationship as well. Edited the question to make the issue clearer. – Neo Apr 10 '13 at 12:07