Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I also couldn't get <code>@Fetch(FetchMode.JOIN)</code> to work when using JPA <em>(although it works fine when using the hibernate Criteria api)</em> and I also couldn't find any examples explaining why, but I can think of a few workarounds.</p> <p>The most straightforward way to load the Groups eagerly, is to use JPQL:</p> <pre><code>public interface PersonRepository extends JpaRepository&lt;Person, String&gt;{ @Query(value = "select distinct p from Person p left join fetch p.groups") List&lt;Person&gt; getAllPersons(); } </code></pre> <p>As you are using spring-data-jpa, you could also load the Groups eagerly by using a <code>Specification</code>. (As of 1.4.x you can chain specs that return null).</p> <pre><code>final Specification&lt;Person&gt; fetchGroups = new Specification&lt;Person&gt;() { @Override public Predicate toPredicate(Root&lt;Person&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) { root.fetch("groups", JoinType.LEFT); query.distinct(true); return null; } }; </code></pre> <p>If neither of these is an option for you, your best bet is probably to use <code>@Fetch(FetchMode.SUBSELECT)</code>.</p> <p>Another option is to use <code>@Fetch(FetchMode.SELECT)</code> in combination with <code>@BatchSize</code>. <code>@BatchSize</code> helps to solve the problem of the n+1 queries. By tweaking the batch size you can reduce the amount of queries executed to CEIL(n/batch_size)+1.</p> <pre><code>@Entity @Table(name = "persons") public class Person { @Id String name; @ManyToMany(fetch = FetchType.EAGER) @BatchSize(size = 20) Set&lt;Group&gt; groups = new HashSet&lt;&gt;(); } @Entity @Table(name = "groups") public class Group { @Id String name; @ManyToMany(mappedBy = "groups", fetch = FetchType.LAZY) Set&lt;Person&gt; persons = new HashSet&lt;&gt;(); } public interface PersonRepository extends JpaRepository&lt;Person, String&gt;{} </code></pre> <p>This mapping results in the following sql when you run <code>personRepository.findAll();</code> on a database containing 10 persons and <code>@BatchSize</code> set to 5.</p> <pre><code>Hibernate: select person0_.name as name1_ from persons person0_ Hibernate: select groups0_.persons_name as persons1_1_1_, groups0_.groups_name as groups2_1_, group1_.name as name0_0_ from persons_groups groups0_ inner join groups group1_ on groups0_.groups_name=group1_.name where groups0_.persons_name in ( ?, ?, ?, ?, ? ) Hibernate: select groups0_.persons_name as persons1_1_1_, groups0_.groups_name as groups2_1_, group1_.name as name0_0_ from persons_groups groups0_ inner join groups group1_ on groups0_.groups_name=group1_.name where groups0_.persons_name in ( ?, ?, ?, ?, ? ) </code></pre> <p><em>Note that <code>@BatchSize</code> also works for collections mapped with <code>FetchType.LAZY</code>.</em></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload