MultipleBagFetchException when join fetch with multiple OneToMany in JPA

If you define multiple `@ OneToMany``` in JPA and try to fetch both with `join fetch```, the following run-time exception may occur.

Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [jpa.sample2.Tweet.reTweets, jpa.sample2.Tweet.favorites]
	at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:76) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
	at org.hibernate.loader.hql.QueryLoader.<init>(QueryLoader.java:110) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]

Status

As a schema for explanation, assume a table of multiple ReTweets and multiple Favorites in one tweet. The entity of java is as follows.

@NoArgsConstructor
@AllArgsConstructor
@Entity
@Data
public class Tweet {
	@Id
	Long id;

	String value;

	@OneToMany
	@JoinColumn(name = "tweetId")
	List<ReTweet> reTweets;

	@OneToMany
	@JoinColumn(name = "tweetId")
	List<Favorite> favorites;
}
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Data
public class ReTweet {
	@Id
	Long id;
	Long tweetId;
	String value;
}
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Data
public class Favorite {
	@Id
	Long id;
	Long tweetId;
	String value;
}

JPQL uses `` `join fetch``` twice as shown below.

@Repository
public interface TweetRepository extends JpaRepository<Tweet, Long>  {	
	@Query("select distinct t from Tweet t "
			+ " left join fetch t.reTweets "
			+ " left join fetch t.favorites"
			+ " order by t.id")
	List<Tweet> list2();
}

This will result in the above run-time exception.

solution

In this case, change `List``` to `Set```.

	@OneToMany
	@JoinColumn(name = "tweetId")
	Set<ReTweet> reTweets;

	@OneToMany
	@JoinColumn(name = "tweetId")
	Set<Favorite> favorites;

Or it may be ``` Map``.

	@OneToMany
	@JoinColumn(name = "tweetId")
	Map<Long, ReTweet> reTweets;

	@OneToMany
	@JoinColumn(name = "tweetId")
	Map<Long, Favorite> favorites;

Alternatively, it is possible to give up a single JPQL and divide it into multiple parts.

	@Query("select distinct t from Tweet t "
			+ " left join fetch t.reTweets "
			+ " order by t.id")
	List<Tweet> list3();
	
	@Query("select distinct t from Tweet t "
			+ " left join fetch t.favorites"
			+ " order by t.id")
	List<Tweet> list4();

Recommended Posts

MultipleBagFetchException when join fetch with multiple OneToMany in JPA
When seeking multiple in a Java array
@BatchDataSource used when defining multiple DataSources in spring-batch
Add an item when logging in with devise
How to define multiple orm.xml in Spring4, JPA2.1