[JAVA] MultipleBagFetchException beim Join-Abruf mit mehreren OneToMany in JPA

Wenn Sie in JPA mehrere @ @ OneToMany``` definieren und versuchen, beide mit `join fetch``` abzurufen, kann die folgende Laufzeitausnahme auftreten.

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

Nehmen Sie als Erklärungsschema eine Tabelle mit mehreren ReTweets und mehreren Favoriten in einem Tweet an. Die Entität von Java ist wie folgt.

@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 verwendet `` `join fetch``` zweimal wie folgt.

@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();
}

Dies führt zu der oben genannten Laufzeitausnahme.

Lösung

In diesem Fall ändern Sie `List``` in` Set```.

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

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

Oder es kann `Map sein.

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

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

Alternativ ist es möglich, ein einzelnes JPQL aufzugeben und es in mehrere Teile zu unterteilen.

	@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 beim Join-Abruf mit mehreren OneToMany in JPA
Bei der Suche nach mehreren in einem Java-Array
@BatchDataSource wird verwendet, wenn mehrere DataSources im Spring-Batch definiert werden
Fügen Sie ein Element hinzu, wenn Sie sich mit devise anmelden
So definieren Sie mehrere orm.xml in Spring4, JPA2.1