I have an small console application and I am using spring-data-jpa with hibernate. I really can not figure out how to lazy initialize collections when using spring-data-jpa
However, I found a way. This method is inside my service implementation:
public Set<Order> fetchUserOrders(Long userId) {
User user = userRepository.findOne(userId);
Hibernate.initialize(user.getOrders());
Set<Order> orders = user.getOrders();
return orders;
}
Note: this is as @zagyi sugested in one of his comments, but also pay attention to the statement: Hibernate.initialize(user.getOrders());
without this the collection still wouldn't be initialized and you will get an error.
One solution can be to make User.orders
an eagerly fetched collection by
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Order> orders = new HashSet<Order>();
Entity associations are lazily loaded by default. This means that the orders
Set is actually just a proxy object that won't get initialized until you invoke a method on it. This is good, because the associated Order
objects won't get loaded unless they are needed. However, this can cause problems, if you try to access the uninitialized collection outside of a running transaction.
If you know that in most of the cases you will need the User's Orders, it makes sense to make the association eagerly fetched. Otherwise you will have to ensure that the collection gets initialized/loaded inside a transaction. The OpenSessionInViewFilter
you mentioned makes sure that the transaction stays open during the request processing, that is why you don't have this issue in yout webapp.
In case you must keep it lazily loaded, try using Spring's TransactionTemplate
to wrap the code in your main method:
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
...
}
});
This worked for me:
@Component
public class Test {
@Inject
OrderDAO orderDAO;
@PersistenceUnit
private EntityManagerFactory emf;
@PostConstruct
public void test(){
EntityManager em= emf.createEntityManager();
for (Order o:orderDAO.findAll()){
o=em.find(o.getClass(),o.getId());
System.out.println(o.getLazyField());
}
em.close();
}
}