0

I'm encountering a problem when merging an existing parent entity with a new child entity.

Here's the scenario:

  1. Create two new parent's and persist in db.
  2. In parent's table we will have two new entries as follows
  3. ID = 0, NAME = A
  4. ID = 1, NAME = B
  5. Using entitymanager.find() , fetch the parent with ID=0, and create a new child for the parent.
  6. In the child's table, we will have the following entry
  7. ID=0, NAME = CHILD of A, PARENT_ID = 0
  8. Using entitymanager.find() , fetch the parent with ID=1, and create a new child for the parent.
  9. After merging the parent object using entitymanager.merge(), the newly created child get's merge with the existing child with ID = 0.
  10. The entries in child table, becomes ID=0 , CHILD OF PARENT B, PARENT_ID =0.

Why does this happen? Shouldn't it create a new entry for Child ?


The parent entity:

public class ParentEntity implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="PARENT_SEQ")
@SequenceGenerator(sequenceName="PARENT_SEQ",schema="MURTAZA YAHYA", name = "PARENT_SEQ", initialValue=-1)
//@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID",unique=true, nullable=false)
private Integer id;

@Column(name="NAME" , length=150)
private String name;

@OneToMany(mappedBy="parentEntity",cascade={CascadeType.MERGE,CascadeType.PERSIST})
List<ChildEntity> childEntities;


public Integer getId() {
    if(id == null)
        return null;
    return id;
}

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

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public List<ChildEntity> getChildEntities() {
    return childEntities;
}

public void setChildEntities(List<ChildEntity> childEntities) {
    this.childEntities = childEntities;
}
}

The Child Entity

public class ChildEntity implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="CHILD_SEQ")
@SequenceGenerator(sequenceName="CHILD_SEQ",schema="MURTAZA YAHYA", name = "CHILD_SEQ" , initialValue=0)
//@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID",unique=true, nullable=false)
private Integer id;

@Column(name="NAME" , length=150)
private String name;

@ManyToOne
@JoinColumn(name="PARENT_ID")
private ParentEntity parentEntity;


public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public ParentEntity getParentEntity() {
    return parentEntity;
}

public void setParentEntity(ParentEntity parentEntity) {
    this.parentEntity = parentEntity;
}




}

public String AddChildToAnExistingParent(Parent p) {
    // TODO Auto-generated method stub

    ParentEntity parent = em.find(ParentEntity.class, p.getId());





     ChildEntity childEntity = new ChildEntity();
     childEntity.setName("INISYA");
     childEntity.setParentEntity(parent);

     List<ChildEntity> list = new ArrayList<ChildEntity>();
     list.add(childEntity);

    parent.setChildEntities(list);

    em.merge(parent);
    return "Success";




}

Any help will be greatly appreciated. Thank you,

ErikEJ
  • 40,951
  • 5
  • 75
  • 115
myh7860
  • 11
  • 2
  • Post the code that reproduces the whole scenario you described. Note that you already have a bug in the posted code: AddChildToAnExistingParent() replaces the list of children with a new list containing a single child, instead of adding a child to the parent as the name suggests it should do. – JB Nizet Aug 01 '15 at 19:38
  • 1
    Please mark the answer as accepted so future readers will see it was helpful. – Gert Arnold Aug 02 '15 at 14:56

1 Answers1

1

As the Parent->Child association is annotated with CascadeType.PERSIST the following code should resolved the described scenario.

public String AddChildToAnExistingParent(Parent p) 
{ // TODO Auto-generated method stub
  ParentEntity parent = em.find(ParentEntity.class, p.getId());
  ChildEntity childEntity = new ChildEntity();
  childEntity.setName("INISYA");
  childEntity.setParentEntity(parent);
  parent.getChildEntities().add (childEntity);
  em.persist(parent);// the cascade.persist cause new childs persistence/insert
  return "Success";
}

For more details in this answer explains the behavior of EntityManager method merge and persist.

Community
  • 1
  • 1
Guillermo
  • 1,523
  • 9
  • 19