@BatchSize with @ManyToMany does not work as expected when migrating 5 -> 6

I have the following entities.

Entity Models:

@Entity
@Getter
@Setter
public class Article {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String categoryId;

    @BatchSize(size = 20)
    @ManyToMany
    private List<Tag> tags = new ArrayList<>();

}
@Entity
@Getter
@NoArgsConstructor
public class Tag {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String name;

    public Tag (String name) {
        this.name = name;
    }
}

And DTO:

@Getter
public class ArticleResponseDto {

    private final int id;
    private final List<TagDto> tags;

    public ArticleResponseDto(Article article) {
        this.id = article.getId();
        this.tags = article.getTags().stream()
                .map(TagDto::new)
                .toList();
    }
}

@Getter
class TagDto {

    private final String name;

    public TagDto(Tag tag) {
        this.name = tag.getName();
    }
}

In Hibernate 5.6.14, when querying articles, it generated queries :

Hibernate: select article0_.id as id1_0_, article0_.category_id as category2_0_ from article article0_ order by article0_.id DESC limit ?
Hibernate: select tags0_.article_id as article_1_1_1_, tags0_.tags_id as tags_id2_1_1_, tag1_.id as id1_2_0_, tag1_.name as name2_2_0_ from article_tags tags0_ inner join tag tag1_ on tags0_.tags_id=tag1_.id where tags0_.article_id in (?, ?, ?, ?, ?)

However In Hibernate 6.1.6:

Hibernate: select t1_0.article_id,t1_1.id,t1_1.name from article_tags t1_0 join tag t1_1 on t1_1.id=t1_0.tags_id where t1_0.article_id in(?,?,?,?,?)
Hibernate: select t1_0.article_id,t1_1.id,t1_1.name from article_tags t1_0 join tag t1_1 on t1_1.id=t1_0.tags_id where t1_0.article_id in(?,?)
Hibernate: select t1_0.article_id,t1_1.id,t1_1.name from article_tags t1_0 join tag t1_1 on t1_1.id=t1_0.tags_id where t1_0.article_id in(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)

Hibernate 6.1.6 generated queries 2 more and binded data in each query were article-id that had empty tag list. And the values in IN clause at the last query was always generated as much as the size of @BatchSize.

Test Code:

@SpringBootTest
@Transactional
class TestServiceTest {

    @Autowired
    private EntityManager entityManager;

    @BeforeEach
    void fixture() {
        List<Tag> tags = List.of(new Tag("t1"), new Tag("t2"), new Tag("t3"));
        List<Tag> tags2 = List.of(new Tag("t4"), new Tag("t5"));

        Article article = new Article();
        Article article2 = new Article();
        Article article3 = new Article();
        Article article4 = new Article();
        Article article5 = new Article();

        article.setTags(tags);
        article3.setTags(tags2);

        tags.forEach(entityManager::persist);
        tags2.forEach(entityManager::persist);

        entityManager.persist(article);
        entityManager.persist(article2);
        entityManager.persist(article3);
        entityManager.persist(article4);
        entityManager.persist(article5);

        entityManager.flush();
        entityManager.clear();
    }

    @Test
    void test() {
        Query query = entityManager.createQuery("select a from Article a");
        List<Article> tech = query.setMaxResults(20).getResultList();
        tech.stream()
                .map(ArticleResponseDto::new)
                .toList();
    }

}

I expected executing queries same in both version, it wasn’t.

Looks like a bug. Please create a JIRA issue for this and attach a reproducer test case.

Thank you. Here it is HHH-16005

1 Like