Joe T
Joe T

Reputation: 31

Hibernate inserting duplicate parent on insertion of child object

I have a parent record that already exists in my database. I am trying to add a child and associate it to this parent. They share the same class. When I attempt to add the child, it remakes the parent entity. It seems like Hibernate is mistakenly thinking that I am making a new parent. Is it a Hibernate tag or maybe there is something getting passed by value instead of reference?

Entity Definition

@Id
@GeneratedValue(generator="entitySequence", strategy=GenerationType.AUTO)
@SequenceGenerator(name="entitySequence", initialValue=1,
sequenceName="entity_sequence", schema="user_portal")
private Long id;

...


@ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, 
CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name="parent_id", referencedColumnName="id")
@JsonBackReference
private Entity parentEntity;


@OneToMany(mappedBy="parentEntity", fetch=FetchType.LAZY, 
targetEntity=Entity.class, 
cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
@JsonManagedReference
private List<Entity> childEntities;

Controller Code

@RequestMapping(
value = "/add",
    method = RequestMethod.POST,
    headers = HTTP_ACCEPT_JSON_HEADER, 
    produces = HTTP_RESPONSE_JSON_HEADER)
public @ResponseBody WebResponse addEntity(@RequestBody Entity s) {
    WebResponse wr = new WebDataResponse();

    try {
        s = EntityService.saveEntity(s);

        if (s != null) {
            handleSuccess(wr, s, 1);
        } else {
            handleSuccess(wr, null, "Error adding Entity.", 0);
        }

    } catch (Exception ex) {
        handleException(wr, ex);
    }

    return wr;
}

Service Code

@Override
@Transactional
public Entity saveEntity(Entity s) {

    String entityNumber = s.getEntityNumber();
    boolean isAddendum = StringUtils.countOccurrencesOf(entityNumber, "-") == 4;


    if(isAddendum) {
Entity parent = getEntityByNumber(entityNumber.substring(0,entityNumber.lastIndexOf("-")));
        if(parent !=null) {
            s.setParentEntity(parent);
        }else {
            return null;
        }
    }

    s.setCreatedBy("admin");
    s.setCreatedDate(new Date());

    s = entityRepository.save(s);

    return s;
}

@Override
@Transactional(readOnly = true)
public Entity getEntityByNumber(String entityNum) {
    Entity s = entityRepository
            .findByEntityNumber(entityNum);

    return s;
}

Any help is greatly appreciated! Thank you!

Upvotes: 2

Views: 1629

Answers (2)

Joe T
Joe T

Reputation: 31

Removing CascadeType.PERSIST from my parentEntity fixed this issue.

I would also recommend NOT manually inserting test variables. It was much better making API test calls using an application like Postman. This gave me a much better idea about how to fix the problem (I received an error rather than this duplication issue).

Upvotes: 1

gtosto
gtosto

Reputation: 1341

You are using a bidirectional association so besides set parent to child you have to add child to parent i.e. parent.getChildEntities().add(s). To be more clear:

@Override
@Transactional
public Entity saveEntity(Entity s) {

  String entityNumber = s.getEntityNumber();
  boolean isAddendum = StringUtils.countOccurrencesOf(entityNumber, "-") == 4;


  if(isAddendum) {
    Entity parent = getEntityByNumber(entityNumber.substring(0,entityNumber.lastIndexOf("-")));
    if (parent !=null) {
        s.setParentEntity(parent);
        parent.getChildEntities().add(s);
    } else {
        return null;
    }
  }

  s.setCreatedBy("admin");
  s.setCreatedDate(new Date());

  s = entityRepository.save(s);

  return s;
}

Upvotes: 0

Related Questions