Yusuf Erdoğan
Yusuf Erdoğan

Reputation: 122

Spring Boot Jpa Fetch Relations Not Working After Save Entity

I have a project with spring boot and hibernate.Everything working well with select data from database but I have a problem after insert entities. Entity relations not fetch after insert. I tried JpaRepository saveAndFlush but didn't work.Also I tried findById didn't work . How can I solve this problem ?

My Entity;

@Entity
@Table(name = "Comment")
@Data
@ApiModel(value = "Comment Model")
public class Comment {

 public static  Comment createCommentFromCommentPostRequest(CommentPostRequest commentPostRequest){
     Comment comment = new Comment();
     comment.setPostId(commentPostRequest.getPostId());
     comment.setUsersId(commentPostRequest.getUsersId());
     comment.setText(commentPostRequest.getText());
     return  comment;
 }

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "id")
 @ApiModelProperty(value = "Comment model autogenerated Id value")
 private Long id;

 @Column(name = "usersId",nullable = false)
 @ApiModelProperty(value = "User Id for describe who commented post")
 private Long usersId;

 @Column(name = "postId",nullable = false)
 @ApiModelProperty(value = "Post Id for describe which post commented")
 private Long postId;

 @Column(name = "text",length = 500)
 @ApiModelProperty(value = "define post content")
 private String text;

 @ManyToOne(fetch = FetchType.EAGER)
 @Fetch(FetchMode.JOIN)
 @JoinColumn(name = "usersId",insertable = false,updatable = false,nullable = false)
 private Users users;

 @ManyToOne(fetch = FetchType.EAGER)
 @JoinColumn(name = "postId",insertable = false,updatable = false,nullable = false)
 @JsonIgnore
 @OnDelete(action = OnDeleteAction.CASCADE)
 private Post post;
}

My Repository;

public interface CommentRepository extends PagingAndSortingRepository<Comment,Long> {
    List<Comment> findAllByPostId(Long postId, Pageable pageable);
}

My Service Method;

public Comment saveOneComment(CommentPostRequest commentPostRequest) {
        //TODO: implement validation
        Comment commentToSave = Comment.createCommentFromCommentPostRequest(commentPostRequest);
        commentToSave= commentRepository.save(commentToSave);
        //I tried JPA repository saveAndFlush 
        return commentRepository.findById(commentToSave.getId()).orElse(null);
    }

My Controller; using saveOneComment endpoint


@RestController
@RequestMapping("/api/comment")
@ApiOperation(value = "Comment api controller")

public class CommentController {

    CommentService commentService;

    public CommentController(CommentService commentService) {
        this.commentService = commentService;
    }

    @GetMapping("/{pageNo}/{pageSize}")
    public List<Comment> getAllComments(@PathVariable int pageNo,@PathVariable int pageSize){

        return Streamable.of(commentService.getAllComments(pageNo,pageSize)).toList();
    }

    @GetMapping("/{commentId}")
    public Comment findCommentById(@PathVariable Long commentId){
        return commentService.findById(commentId);
    }

    @GetMapping("/postId={postId}/{pageNo}/{pageSize}")
    public List<CommentResponse> getAllCommentsByPostId(@PathVariable Long postId,@PathVariable int pageNo,@PathVariable int pageSize){
        return commentService.getAllCommentsByPostIdAsCommentResponse(postId,pageNo,pageSize);
    }

    @PostMapping
    public Comment saveOneComment(@RequestBody CommentPostRequest commentPostRequest){

        return commentService.saveOneComment(commentPostRequest);
    }

    @PutMapping("/{commentId}")
    public Comment putOneComment(@PathVariable Long commentId,@RequestBody CommentPostRequest commentPostRequest){
        return commentService.putOneCommentById(commentId,commentPostRequest);
    }

    @DeleteMapping("/{commentId}")
    public void deleteOneComment(@PathVariable Long commentId){
        commentService.deleteById(commentId);
    }
}

Comment(id=32, usersId=2, postId=2, text=ddwad, users=null, post=null) After insert and find again, users and post is null. When I run getAllCommentsByPostId method everything is fine.

after insert only insert query in console.There is not any query for select statement.

 insert 
    into
        Comment
        (postId, text, usersId) 
    values
        (?, ?, ?)

Upvotes: 1

Views: 2148

Answers (2)

machaxX
machaxX

Reputation: 129

I think the issue here is that data is always getting fetched from hibernate cache. If you enable the SQL queries, you won't see any select queries happening when this code is called -

return commentRepository.findById(commentToSave.getId()).orElse(null);

Although, there has to be a better way to handle this. The only way I can think of here is to either use EntityManager.clear() or EntityManager.refresh(commentToSave).
These techniques will force hibernate to detach the managed entities and fetch data from db again. I prefer refresh as it only refreshes the passed entity.

Now JPA repos don't expose entity manager or clear/flush methods. You would have to do a CustomRepo Implementation to expose refresh method on all your repos. Checkout this article for step by step instruction - https://dzone.com/articles/adding-entitymanagerrefresh-to-all-spring-data-rep

Finally you need to call refresh after saving and flushing like this -

public Comment saveOneComment(CommentPostRequest commentPostRequest) {
    //TODO: implement validation
    Comment commentToSave = Comment.createCommentFromCommentPostRequest(commentPostRequest);
    commentToSave= commentRepository.saveAndFlush(commentToSave); 
    commentRepository.refresh(commentToSave);
    return commentToSave;
}

Upvotes: 2

Amro Nahas
Amro Nahas

Reputation: 54

you have to reload the object again after committing the transaction, i mean outside the transaction to maintain the relations

  @PostMapping
 public Comment saveOneComment(@RequestBody CommentPostRequest commentPostRequest){
      
             Long id= commentService.saveOneComment(commentPostRequest);
        return commentService.loadCommentById(id);
    }
    ````

Upvotes: 1

Related Questions