简体   繁体   中英

lazy loaded list of object in spring jpa transactional service is empty

I am using Spring data jpa in the backend codes. I have included entities, service and controller codes.

The sample codes are simple. Topic and Comment are OneToMany relationship. Comments are configured to be lazy loaded. Now if I calls updateTopic to update topic. In the console, I will see a query to fetch the comments list from the comment table, and then it will update the topic table. But the comments list is empty even though it does have some comments linked with the topic.

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

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "NAME", length = 45)
    @NotNull
    private String name;

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

}
@Entity
@Table(name = "COMMENT")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Comment implements Serializable {
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
        
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "Topic_ID")
    private Topic topic;

   
}

@Service
@Transactional
public class TopicService {
   private final TopicRepository topicRepository ;

   public TopicService(TopicRepository topicRepository ) {
      this.topicRepository = topicRepository ;
   }

   public Topic updateTopic(Topic topic) {
      Topic newTopic = topicRepository.save(topic);
      System.out.println("from service: " + newTopic.getComments().size());
      return newTopic;
   } 
}

Then if I tried to get the comments from the controller instead, then the comment list is not empty. In the console, it will show the update query, then the select query to get comments list. My question is how I can lazy load the comments list from the service class? It seems to be related to the transactional session.


@RestController
@RequestMapping("/api")
public class TopicRestController {
  
   @PutMapping("/release/{id}")
   public Topic updateTopic(@PathVariable long id, @RequestBody Topic newTopic ) {
      return topicService.getTopicById(id)
         .map(topic-> {
            Topic t = topicService.updateTopic(newTopic);
            System.out.println("controller: " + topic.getComments().size());
         })
         .orElseThrow(() -> new CustomException("The topic with id: " + id + " cannot be found", HttpStatus.NOT_FOUND));
   }
   
  
}

You have to map them to DTOs somehow. You may see my article in the profile for details. Please, don't use FetchType.EAGER, it will affect the performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM