[hibernate-issues] [JIRA] (HHH-13740) Problem with duplicates when fetching multiple many-to-many relations with Hibernate FetchMode.JOIN

Evgeniy Khyst (JIRA) jira at hibernate.atlassian.net
Sun May 3 14:30:42 EDT 2020


Evgeniy Khyst ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%3A91620963-4f42-4dc7-a094-4b4322ea6762 ) *updated* an issue

Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 ) / Bug ( https://hibernate.atlassian.net/browse/HHH-13740?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 ) HHH-13740 ( https://hibernate.atlassian.net/browse/HHH-13740?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 ) Problem with duplicates when fetching multiple many-to-many relations with Hibernate FetchMode.JOIN ( https://hibernate.atlassian.net/browse/HHH-13740?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 )

Change By: Evgeniy Khyst ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%3A91620963-4f42-4dc7-a094-4b4322ea6762 )

When there are multiple many-to-many relations with {{FetchMode.JOIN}}, {{session.find}} returns a result with a child relation of type {{List}} containing duplicates.

To avoid {{MultipleBagFetchException: cannot simultaneously fetch multiple bags}} when multiple {{@ManyToMany}} collections have {{@Fetch(FetchMode.JOIN)}}, only one collection has type {{List}} and others have type {{Set}}.

{code:java}@Entity
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Book implements Serializable {

@Id
@GeneratedValue
private Long id;

@NaturalId
@EqualsAndHashCode.Include
private String isbn;

private String title;

private LocalDate publicationDate;

@ManyToMany
@Fetch(FetchMode.JOIN)
private List<Author> authors = new ArrayList<>();

@ManyToMany
@Fetch(FetchMode.JOIN)
private Set<Category> categories = new LinkedHashSet<>();
}{code}

With the following test data

{code:java}softwareDevelopment = new Category("Software development");
session.save(softwareDevelopment);

systemDesign = new Category("System design");
session.save(systemDesign);

martinFowler = new Author("Martin Fowler");
session.save(martinFowler);

gregorHohpe = new Author("Gregor Hohpe");
session.save(gregorHohpe);

gregorHohpe = new Author();
gregorHohpe.setFullName("Gregor Hohpe");
session.save(gregorHohpe);

bobbyWoolf = new Author();
bobbyWoolf.setFullName("Bobby Woolf");
session.save(bobbyWoolf);

poeaa = new Book();
poeaa.setIsbn("007-6092019909");
poeaa.setTitle("Patterns of Enterprise Application Architecture");
poeaa.setPublicationDate(LocalDate.parse("2002-11-15"));
poeaa.getAuthors().addAll(List.of(martinFowler));
poeaa.getCategories().addAll(List.of(softwareDevelopment, systemDesign));
session.save(poeaa);

eip = new Book();
eip.setIsbn("978-0321200686");
eip.setTitle("Enterprise Integration Patterns");
eip.setPublicationDate(LocalDate.parse("2003-10-20"));
eip.getAuthors().addAll(List.of(gregorHohpe, bobbyWoolf));
eip.getCategories().addAll(List.of(softwareDevelopment, systemDesign));
session.save(eip);{code}

a Book entity found by ID contains duplicates in {{List<Author> authors}} because {{Set<Category> categories}} has size 2: {{["Software development", "System design"]}}.

{code:java}@Test
void testFindByIdNoTrans findByIdOneAuthor () {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
Book poeaa Transaction transaction = session. find beginTransaction ( Book.class, this.poeaa.getId( ) ) ;

Book eip poeaa = session.find(Book.class, this. eip poeaa.getId());

assertThat(poeaa.getTitle()).isEqualTo(this.poeaa.getTitle());
//    The following line results in exception
//    because the actual poeaa.authors contains duplicates: ["Martin Fowler", "Martin Fowler"]
assertThatHasAuthors(poeaa, martinFowler.getFullName());

transaction.commit();
}
}{code}

{code:java}List<Author> authors = ["Martin Fowler", "Martin Fowler"]{code}

{code:java}@Test
void findByIdTwoAuthors() {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();

Book eip = session.find(Book.class, this.eip.getId());
assertThat(eip.getTitle()).isEqualTo(this.eip.getTitle());
//    The following line results in exception
//    because the actual eip.authors contains duplicates: ["Gregor Hohpe", "Gregor Hohpe", "Bobby Woolf", "Bobby Woolf"]
assertThatHasAuthors(eip, gregorHohpe.getFullName(), bobbyWoolf.getFullName());

transaction.commit();
}
}{code}

{code:java}List<Author> authors = [" Martin Fowler Gregor Hohpe ", " Martin Fowler Gregor Hohpe " ]{code}

Probably , because {{categories}} has size 2:

{code:java}Set<Category> categories = [ " Software development Bobby Woolf ", " System design Bobby Woolf "]{code}

When there There are 2 authors and 2 categories there are no duplicates in child relations.

Beginning transaction with {{ session.beginTransaction() List<Author> authors }} doesn't have any effect on the duplicates when {{Set<Category> categories}} has size 1.

See the test [https://github.com/evgeniy-khist/hibernate-fetch-mode-join/blob/master/src/test/java/com/example/hibernate/BookFetchModeJoinWithSetTests.java|https://github.com/evgeniy-khist/hibernate-fetch-mode-join/blob/master/src/test/java/com/example/hibernate/BookFetchModeJoinWithSetTests.java|smart-link] .

Using The same problem is present when using Spring Data JPA and making the test transactional with {{@org.springframework.transaction.annotation.Transactional}} solves the problem with duplicates. ( Spring Boot version - 2.2. 1 6.RELEASE, Spring Data JPA version - 2.2. 1 6.RELEASE, Hibernate version - 5.4. 8 12.Final.

See the test [https://github.com/evgeniy-khist/spring-data-jpa-fetch-mode-join/blob/master/src/test/java/com/example/spring/data/jpa/BookFetchModeJoinWithSetTests.java|https://github.com/evgeniy-khist/spring-data-jpa-fetch-mode-join/blob/master/src/test/java/com/example/spring/data/jpa/BookFetchModeJoinWithSetTests.java|smart-link] .

( https://hibernate.atlassian.net/browse/HHH-13740#add-comment?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-13740#add-comment?atlOrigin=eyJpIjoiNDg0MmQzNWRiZmUyNDkyZTgzNThkNWJjMDhjMzQyZTMiLCJwIjoiaiJ9 )

Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.core&referrer=utm_source%3DNotificationLink%26utm_medium%3DEmail ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailNotificationLink&mt=8 ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100125- sha1:e76aa5f )
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/hibernate-issues/attachments/20200503/4e173c79/attachment.html 


More information about the hibernate-issues mailing list