Почему получение множества связаных полей в рамках транзакции вызывают failed to lazily initialize spring boot

Рейтинг: 0Ответов: 1Опубликовано: 03.03.2025

UserController

@GetMapping("/{id}/posts")
    public ResponseEntity<?> getPosts(@PathVariable("id") Long id) {
        List<Post> postsList = userService.getAllUserPosts(id);
        System.out.println(postsList);
        return ResponseEntity.status(HttpStatus.OK).body(postsList);
    }

метод из userService

@Transactional
    public List<Post> getAllUserPosts(Long userId) {
        User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("Not found"));
        return user.getPosts();
    };
@Entity
@Table(name = "users")
@Getter
@Setter
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String username;

    private String password;

    @OneToMany(mappedBy = "user")
    @JsonManagedReference
    private List<Post> posts;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String title;

    @CreatedDate
    private LocalDateTime createdDate;

    @ManyToOne(optional = false)
    @JsonBackReference
    private User user;

    public Post(String title, User user) {
        this.title = title;
        this.user = user;
    }
}

почему когда я запрашиваю множество связанных полей Posts выбрасывается ошибка, хотя запрос постов я делаю в рамках транзакции и соответственно во время выполнения метода, конекшн с БД есть.

БД: postgresql, Spring Boot

Ошибка:

2025-03-03T15:54:33.161+02:00 WARN 32236 --- [dataJpa] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.datajpa.entity.User.posts: could not initialize proxy - no Session]

Ответы

▲ 0

Метод getPosts вызывается вне транзакции. Обращатся к заглушкам можно только в рамках транзакции.

Надо либо повесить @Transactional на getPosts.

Либо отказатся от ленивой инициализации.

Обычно эту проблему решают при помощи DTO, которые возвращают из методов сервисов вместо Entity.