Can't add data to a list via Postman Spring JPA @OneToMany/@ManyToOne

487 Views Asked by At

I am learning spring-boot jpa and is starting to get a feel on how thing works unfortunately I came across some difficulty. My sample app is so simple and only have three entities, namely MemberInfo, MemberProfile, MemberTalents.

My Entities code goes like this:

@Entity
@Table(name="member_info")
public class MemberInfo {
  //...
  @OneToOne(cascade=CascadeType.ALL)
  @JoinColumn(name="memberProfileId")
  private MemberProfile memberProfile;
  // getters and setters
}

@Entity
@Table(name="member_profile")
public class MemberProfile {
  //...
  @OneToOne(mappedBy="memberProfile")
  private MemberInfo memberInfo;

  @OnetoMany(mappedBy="memberProfile")
  private Set<MemberTalent> memberTalent = new Hashset<>();
  
  // getters and setters

  public void addMemberTalent(MemberProfile memberProfile) {
      memberTalent.add(memberProfile);
  }

}

@Entity
@Table(name="member_talent")
public class MemberTalent {
  //...
  @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
  @JoinColumn(name="memberProfileId")
  private MemberProfile memberProfile;
  // getters and setters
}

I successfully configured MySQL for this entities and upon running in local host and send POST command in Postman using this format.

{
    "memberUserId": 1,
    "memberUser": "John69",
    "memberEmail": "[email protected]",
    "memberProfile": {}
}

I get this response.

[
  {
    "memberUserId": 1,
    "memberUser": "John69",
    "memberserEmail": "[email protected]",
    "memberProfile": {
        "memberProfileId": 1,
        "memberName": null,
        "memberAddress": null,
        "memberTalent": []
    }
  }
]

Now, using Put command I managed to edit memberProfile with id=1, using this command.

{
"memberProfileId": 1,
"memberName": "John Doe",
"memberAddress": "[email protected]",
}

And I get this response

{
    "memberUserId": 1,
    "memberUser": "John69",
    "memberserEmail": "[email protected]",
    "memberProfile": {
        "memberProfileId": 1,
        "memberName": "John Doe",
        "memberAddress": "[email protected]",
        "memberTalent": null
}

Now, my challenge is filling the member talent list. This is the code I came up with.

@PostMapping("/{memberProfileId}/talents")
MemberProfile addNewTalent(@PathVariable long memberProfileId, @RequestBody 
                            MemberTalent memberTalent) {
    MemberProfile memberProfile = memberProfileService.findById(memberProfileId);
    memberProfile.addMemberTalent(memberTalent);
    return memberProfileService.save(memberProfile);
}

Unfortunately, it won't add anything to the memberTalent list. If anyone can help me on this I will really appreciate it. Thank you.

Updating:

Here is the API body I sent in PostMapping:

{
  "memberTalent": "Guitar",
  "memberMastery": "Expert"
}

And here is the response. Even if I send many Post request, the response is the same.

{
    "memberUserId": 1,
    "memberUser": "John69",
    "memberserEmail": "[email protected]",
    "memberProfile": {
        "memberProfileId": 1,
        "memberName": "John Doe",
        "memberAddress": "[email protected]",
        "memberTalent": [
              {
                 "memberTalentId": 0,
                 "memberTalent": null,
                 "memberMastery": null
              }

     ]
}
1

There are 1 best solutions below

3
On

You are returning memberProfileService.save(memberProfile) & as per save code, it is returning em.merge :

@Transactional
    @Override
    public <S extends T> S save(S entity) {

        Assert.notNull(entity, "Entity must not be null.");

        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }

When you are returning merge, then it is not returning your entire entity. So you have to use below code to correctly return entire entity :

@PostMapping("/{memberProfileId}/talents")
MemberProfile addNewTalent(@PathVariable long memberProfileId, @RequestBody 
                            MemberTalent memberTalent) {
    MemberProfile memberProfile = memberProfileService.findById(memberProfileId);
    memberProfile.addMemberTalent(memberTalent);
    memberProfileService.save(memberProfile);
    return memberProfileService.findById(memberProfileId);
}