0

Am getting an error while updating the existing entity with below approach using PostRepository save method.

Here are my objects,

@Entity
public class Post {
  @Id
  private String postId;
  private String postName;
  @OneToMany(mappedBy = "Post", cascade = CascadeType.ALL)
  private Collection<PostTag> postTags = new HashSet<PostTag>();
}

@Entity
public class Tag {
  @Id
  private String tagId;
  private String tagName;
  @OneToMany(mappedBy = "tag", cascade = CascadeType.ALL)
  @JsonIgnore
  private Collection<PostTag> postTags = new HashSet<PostTag>();
}

@Entity
public class PostTag {
  @EmbeddedId
  private PostTagId postTagId = new PostTagId();
  
  @ManyToOne
  @MapsId("postId")
  @JoinColumn(name = "post_Id")
  @JsonIgnore
  private Post post;
  
  @ManyToOne
  @MapsId("tagId")
  @JoinColumn(name = "tag_Id")
  private Tag tag;
  
  //extra columns ommited
}


@Embeddable
public class PostTagId implements Serializable {
  private String postId;
  private String tagId;
  //equals & hashcode ommited
}

I try to save the post as in the form of below POST json,

{
  "postId": "post-001",
  "postName": "post-001",
  "postTags": [
    {
      "tag": {
        "tagId": "tag-001",
        "tagName": "tag-001"
      }
    }
  ]
}

Service implementation looks as below,

public Post save(Post post){
    Post newPost = new Post();
    newPost.setPostName(Post.getPostName());
    newPost.setPostId(Post.getPostId());
    for (PostTag posttag : post.getPostTags()) {
      PostTag newPostTag = new PostTag();
      Tag dbTag = tagRepo.getById(posttag.getTag().getTagId());
      if(dbTag == null){
        Tag newtag = new Tag();
        newtag.setTagId(posttag.getTag().getTagId());
        newtag.setTagName(posttag.getTag().getTagName());
        tagRepo.save(newTag);
        dbTag = newTag;
      }
      newPostTag.setTag(dbTag);
      newPostTag.setPost(newPost);
      newPost.getPostTags().add(newPostTag);
    }
    return PostRepository.save(newPost);
}

The above code works first time and creates record in POST & TAG & POSTTAG. But when i run the save again with same input it complains below error,

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [PostTagId@c03f34a0]

Clearly it says there is already an obj which is there in PostId + TagId combination, But how can i just do update or merge in that case for only PostTag entity extra fields if there is already same combination available?

Please help.

Satscreate
  • 495
  • 12
  • 38

1 Answers1

-1

There was already same question on next link, so it maybe helps you: answer

Iva Levak
  • 27
  • 3
  • so I always need to get the existing posttag based on posttagid and and modify is it? Why not let hibernate do that, make an update if it sees entity already? – Satscreate Jun 12 '21 at 03:11
  • Actually, you need only use save() to update existing entities and save new ones. But I think error shows because objects in Post or Tag are not refering to same object PostTag, in contrast to refering to same row. Alternatively, you can make sure that objects in Tag and Post are refering to same object PostTag by searching it in list and modifying it. Then you only need to save Tag or Post entity. If you want to escape this, you can remove cascading, or specify it (like CascadeType.REMOVE ). In this case make sure that if Post entity is deleted then PostTag must be deleted to etc. – Iva Levak Jun 13 '21 at 20:30
  • Thanks for the comment. what i mean from your comment "you can make sure that objects in Tag and Post are refering to same object PostTag by searching it in list and modifying it. " is get the TagPost from the database like findBy tagpost and do modification on top? am i right. – Satscreate Jun 14 '21 at 07:17
  • You don't have to find it in database by searching TagPost, you can find Tag by it's id, then add PostTag to Collection in Tag object and save it. I can see that you defined collections of object PostTag in Tag and Post. This will result with same behaviour like finding specifig PostTag by tag_id. So it feels like you're updating values instead of hibernate. In your code there is already called function "tagRepo.getById()" so you only need to make case when tag is not null and modify collection od tag (add or change PostTag), and save it. – Iva Levak Jun 14 '21 at 18:07