15

I have an entity containing a List that is thus lazy loaded by default:

interface MyEntityRepository extends CrudRepository<MyEntity, Long> {

}

@Entity
public class MyEntity {
    @Id
    private Long id;

    @OneToMany(mappedBy = "bar") //lazy by default
    private List<Bar> bars;
}

@Entity
public class Bar {
    //some more
}

Question: How can I force eager loading when executing repository.findOne(id)?

membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • 1
    `@OneToMany(fetch=FetchType.EAGER)` will this help ? – Jebil Aug 06 '15 at 11:57
  • 4
    I know I can force the `eager` mode like this. But I want to stick to the `lazy` default and just force eager on all lists on one specific select. – membersound Aug 06 '15 at 12:02
  • Well then, If you're using criteria in DAO you can force fetch type by `criteria.setFetchMode("bars", FetchMode.EAGER)` – Jebil Aug 06 '15 at 12:05
  • 2
    or you can use `MyEntity p = (MyEntity) sess.get(MyEntity.class, id); Hibernate.initialize(p.getBars());` – Jebil Aug 06 '15 at 12:11
  • 2
    So that would imply writing my own criterea. Which is fine in general, but I hope spring-data would bring something for this. – membersound Aug 06 '15 at 12:29
  • you can write a query @Query("select m from MyEntity m LEFT JOIN FETCH m.bars") MyEntity findOne(Long id); – Rafael Zeffa Aug 06 '15 at 12:29

3 Answers3

20

You can force eager fetch writing custom HQL query with left join fetch, eg:

interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
    @Query("select e from MyEntity e left join fetch e.bar b where e.id = ?1")
    MyEntity findOne(long id)
}
1

I needed this too and as I'm calling the dao inside a service object that is insise a transaction I call call the get method so no exception and I was able to fetch the records. Something like in java 8:

public ProductEntity findProduct(int id) {
    ProductEntity p = productRepository.findOne(id);
    p.getPresentations().stream().count();
    return p;
}

p.getPresentations().stream().count(); will force the fetch, I know is not a clean way to do it but it gets the job done in the mean time

yedpodtrzitko
  • 9,035
  • 2
  • 40
  • 42
Luis Rocha
  • 50
  • 4
-9

Change your mapping from

@OneToMany(mappedBy = "bar") //lazy by default

To

@OneToMany(mappedBy = "bar", fetch = FetchType.EAGER) //lazy by default
  • 3
    To quote myself: "I know I can force the eager mode like this. But I want to stick to the lazy default and just force eager on [...] one specific select" – membersound Oct 25 '17 at 08:04