0

Imagine an scenario like:

CREATE TABLE PARENT (id BIGINT, name VARCHAR);

and

CREATE TABLE CHILD (id BIGINT, name VARCHAR, parent_id BIGINT FOREIGN KEY REFERENCES PARENT(id));

This, translated in JPA entities, would be something like:

Parent.java:

  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
private List<Child> child;

Child.java:

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) //Child should not modify parent (except for its List<> of childs)
@JoinColumn(name = "parentId", updatable = false, insertable = false)
private Parent parent;

I don't know how to achieve the following setting:

  • When parentRepository.saveOrMerge(parent) is executed, both parent and its child on the set should be persisted. If parent's child Set has been updated from db state, changes should applied to child table as well. (This is the orphanRemoval flag, I guess). If the state of a particular child has changed, this should be persisted as well (this is the CascadeType.ALL on the parent-side, I guess).
  • When parentRepository.remove(parent) is executed, both parent and its child should be removed. Like an ON DELETE CASCADE, anything that references parent should be deleted even if the managed entity had a Child Set cleared. I dont know if this is possible through JPA.

  • When childRepository.saveOrMerge(child) is executed, child should be persisted, and if the parent object is not persisted, it should be persisted as well. In case the parent is in db and the child has a modified instance, changes should be discarded. (I guess this is the updatable=false and insertable=true) flags

  • When childRepository.remove(child) is executed, child should be removed from db, AND from any parent's set in memory. If this was the only child the parent had, parent should not be deleted (I guess this is the omission of CascadeType.REMOVE on the child-side relation)

Currently with the previous code, bullet point #4 is not achievable. Is there anyway I can indicate parent's child set should be automatically updated if I childRepository.remove(child) only by means of JPA annotations in the entity ? I would like to avoid having to use parentRepository when I want to delete a child. I find unnatural the only way to achieve all of this is by removing my child from the parent set and saving parent. What's the point of a ChildRepository then, if updating the Set in the parent and saving the parent is enough for everything?

Whimusical
  • 6,401
  • 11
  • 62
  • 105
  • can you remove orphanRemoval=true from your child class or make it false? – GauravRai1512 Nov 21 '18 at 14:20
  • its a bad idea to use any of the parameters in @ManyToOne side. – Alien Nov 21 '18 at 14:26
  • @GauravRai1512 Why? Even if I plan to enable the removal of childs directly in the entity manager, it makes sense that if I save the parent with a modified list of childs it also updates the child table – Whimusical Nov 21 '18 at 14:30
  • @Alien I was just testing, my only purpose for the non-REMOVE cascades is trying to make parent List autoupdated in case I execute a repository.remove(child) – Whimusical Nov 21 '18 at 14:31
  • What exactly do you mean by *looks like parent set is not updated*? You load a parent and the child is still there? You have an existing in-memory parent and the child still exists? – Alan Hay Nov 21 '18 at 16:10
  • @Alan Hay Yes, if I do childrepository.remove(child) then if I do parentrepository.findone(parent) it still contains the child in its List getChild() – Whimusical Nov 21 '18 at 16:13
  • You should add all the relevant code i.e. that where you delete and reload. – Alan Hay Nov 21 '18 at 16:15
  • @Alan Hay I just did :) – Whimusical Nov 21 '18 at 16:30
  • 1
    Cascading options have zero effect on in-memory data.You need to maintain in-memory data yourself. While you may find it unnatural to work with parent repo that is a widely accepted design pattern: https://stackoverflow.com/questions/1958621/whats-an-aggregate-root – Alan Hay Nov 21 '18 at 17:17
  • I see... thanks for the info. Can you please create a formal answer so I can accept it? – Whimusical Nov 21 '18 at 18:35

0 Answers0