0

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": "John@gmail.com",
    "memberProfile": {}
}

I get this response.

[
  {
    "memberUserId": 1,
    "memberUser": "John69",
    "memberserEmail": "John@gmail.com",
    "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": "doe@moon.com",
}

And I get this response

{
    "memberUserId": 1,
    "memberUser": "John69",
    "memberserEmail": "John@gmail.com",
    "memberProfile": {
        "memberProfileId": 1,
        "memberName": "John Doe",
        "memberAddress": "doe@moon.com",
        "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": "John@gmail.com",
    "memberProfile": {
        "memberProfileId": 1,
        "memberName": "John Doe",
        "memberAddress": "doe@moon.com",
        "memberTalent": [
              {
                 "memberTalentId": 0,
                 "memberTalent": null,
                 "memberMastery": null
              }

     ]
}
newB
  • 1
  • 1

1 Answers1

0

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);
}
Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
  • Hello Ashish, I'm kinda lost to the first piece of code. I have used the @Transactional annotation in my MemberProfileServiceImpl, with the method Public MemberProfile save(MemberProfile memberProfile). Is it here should I insert the 1st piece of code? Or should I do it in the MemberTalentServiceImpl as well? – newB Aug 07 '22 at 12:04
  • @newB, no, first piece of code is actual `save` implementation which I have shown for your reference. what ideally you should do is to use my second piece of code as your implementation of `addNewTalent` – Ashish Patil Aug 07 '22 at 12:14
  • I understand, I am trying it now. Thank you so much, really appreciate it. – newB Aug 07 '22 at 15:22