Коллекция сущностей извлекается, несмотря на то, что FetchType.LAZY в Hibernate заявлен - PullRequest
0 голосов
/ 29 марта 2020

Я не понимаю поведение FetchType.LAZY в моей ситуации. В одном случае hibernate работает должным образом (он не выбирает объекты, отмеченные как FetchType.LAZY), но когда дело доходит до другого объекта, hibernate выбирает связанные объекты, даже если они тоже помечены как FetchType.LAZY.

У меня есть две сущности, которые имеют отношение к этой проблеме. Их фрагменты (с контроллерами и службами):

Сообщение:

@Entity
@Table(name = "POST")
@ToString @Getter @Setter @RequiredArgsConstructor
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")
public class Post extends BaseEntity {

    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
    private Set<Comment> comments = new HashSet<>();
}

Комментарий:

@Entity
@Table(name = "COMMENT")
@ToString @Getter @Setter @RequiredArgsConstructor
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")
public class Comment extends BaseEntity {

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
    @JoinColumn(name = "post_id")
    private Post post;
}

BaseEntity:

@MappedSuperclass
@Getter @Setter
public class BaseEntity {
    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;
}

Их контроллеры & services:

PostController:

@RestController
@RequestMapping("/api/posts")

public class PostController {

private final PostService postService;

@Autowired
public PostController(PostService postService) {
    this.postService = postService;
}

@GetMapping
public List<Post> getAllPosts(Pageable pageableRequest){
   Page<Post> resultPage = postService.getAll(pageableRequest);
   if(pageableRequest.getPageNumber() > resultPage.getTotalPages()){
       throw new InvalidOperationException("Page not found. Last available page: " + resultPage.getTotalPages());
   }

   return resultPage.getContent();
}

PostService:

@Service
@Transactional
public class PostService {

    private final PostRepository postRepository;

    @Autowired
    public PostService(PostRepository postRepository) {
        this.postRepository = postRepository;
    }


    public Page<Post> getAll(Pageable pageableRequest) {
        return postRepository.findAll(pageableRequest);
    }
}

postRepository.findAll (pageableRequest) - метод из PagingAndSortingRepository.

CommentController:

@RestController
@RequestMapping("/api/comments")
public class CommentController {

    private final CommentService commentService;

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

    @GetMapping
    public List<Comment> getAllComments(){
        return commentService.getAll();
    }
}

CommentService:

@Service
@Transactional
public class CommentService {

    private final CommentRepository commentRepository;

    @Autowired
    public CommentService(CommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }

    public List<Comment> getAll(){
        return commentRepository.findAll();
    }
}

commentRepository.findAll () из JpaRepository.

Когда я пытаюсь получить все комментарии (используя конечную точку "/ api / comments ") hibernate работает нормально, на мой взгляд, и исключение выдается, поскольку сущность не извлекается из базы данных:

nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->pl.app.model.Comment["post"]->pl.app.model.Post$HibernateProxy$d4g0rJFB["hibernateLazyInitializer"])] with root cause

Проблема в том, что я пытаюсь получить сообщения (используя конечную точку" / api / posts ") - комментарии получены. Hibernate создает операторы select для получения комментариев к сообщениям:

    Hibernate: select post0_.id as id1_2_, post0_.content as content2_2_, post0_.user_id as user_id3_2_ from post post0_ limit ?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?

Если я получаю комментарий (сообщение является связью в комментарии), эти операторы создаются (и после того, как выдается последнее исключение оператора select):

Hibernate: select comment0_.id as id1_1_, comment0_.content as content2_1_, comment0_.user_id as user_id3_1_, comment0_.post_id as post_id4_1_ from comment comment0_
Hibernate: select post0_.id as id1_2_0_, post0_.content as content2_2_0_, post0_.user_id as user_id3_2_0_ from post post0_ where post0_.id=?
Hibernate: select categories0_.post_id as post_id1_0_0_, categories0_.category as category2_0_0_ from category categories0_ where categories0_.post_id=?
Hibernate: select comments0_.post_id as post_id4_1_0_, comments0_.id as id1_1_0_, comments0_.id as id1_1_1_, comments0_.content as content2_1_1_, comments0_.user_id as user_id3_1_1_, comments0_.post_id as post_id4_1_1_ from comment comments0_ where comments0_.post_id=?

Мои вопросы:

Почему hibernate выбирает комментарии, когда я явно указал FetchType.LAZY для коллекции комментариев в сущности Post?

Может, наоборот? Это означает, что сообщение должно быть получено, когда я получаю комментарий, даже если используется FetchType.LAZY?

...