Home > database >  lazy load does not work in Spring data jpa
lazy load does not work in Spring data jpa

Time:12-08

I am using spring jpa and lombok to define the java bean Topic. Each topic will have many comments. My onetomany configuration is

@Entity
@Table(name = "TOPIC")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Topic implements Serializable {

@OneToMany(
            fetch = FetchType.LAZY, 
            cascade = CascadeType.REMOVE,
            mappedBy = "topic"
        )
    private Set<Comment> comments= new HashSet<>();

The restful api I created is like this. The serialization seems to be the issue, and it always fetch the comments. As mentioned by Chris, I have added @JsonIgnore, and it seems solving the issue. But what if I want to load the comments, @JsonIgnore won't return the comments in the serialization.

@GetMapping("/topics")
   public List<Topic> getAllTopics(@SortDefault(sort = "topicName", direction = DESC) Sort sort) {
      return topicService.getAllTopics(sort);
   }

CodePudding user response:

I believe that what you actually need is a projection. Lazy fetch is not something that can be easily configured runtime not to mention preventing loading lazy items.

Instead you should declare the data you want to be fetched from the database with a DTO class or even better with an interface telling what to show.

See below repository (I have omitted the service part since you did not show it either):

public interface TopicRepository extends PagingAndSortingRepository<Topic, Long> {  
    List<Topic> findAll(Sort sort);

    // bean convention getter declarations for fields to fetch
    interface TopicWithoutComments {
        Long getId();
        String getTopicName();
    }

    List<TopicWithoutComments> findAllBy(Sort sort);
}

Now yiu need separate methods (or any other way you want to decide whether to show or not the comments), first the original:

@GetMapping("/topics")
public List<Topic> getAllTopics(@SortDefault(sort = "topicName", 
        direction = Direction.DESC) Sort sort) {
    return topicRepository.findAll(sort);
}

It outputs something like:

Hibernate: select comments0_.topic_id as topic_id3_0_0_, comments0_.id as id1_0_0_, comments0_.id as id1_0_1_, comments0_.text as text2_0_1_, comments0_.topic_id as topic_id3_0_1_ from comment comments0_ where comments0_.topic_id=?
...

for each Topic found. Then the projection endpoint could be like:

@GetMapping("/topics/wocomments")
public List<TopicWithoutComments> getAllTopicsWithoutComments(
        @SortDefault(sort = "topicName",
            direction = Direction.DESC) Sort sort) {
    return topicRepository.findAllBy(sort);
}

which would print only one line (assuming there are no other one-to-many relationships on Topic):

Hibernate: select topic0_.id as col_0_0_, topic0_.topic_name as col_1_0_ from topic topic0_ order by topic0_.topic_name desc

  • Related