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 with its repositories, in an standalone console application. Here is some of my code:
@Entity
public class User {
...
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="USER_ORDER_ID")
private Set<Order> orders = new HashSet<Order>();
...
}
repository:
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
public ArrayList<User> findByFirstNameIgnoreCase(String firstName);
}
service impl:
@Service
@Repository
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
public ArrayList<User> findByFirstNameIgnoreCase(String firstName) {
ArrayList<User> users = new ArrayList<User>();
users = userRepository.findByFirstNameIgnoreCase(firstName);
return users;
}
my main method:
...
user = userRepository.findByFirstNameIgnoreCase("john").get(0);
orders = user.getOrders();
for (Order order : orders) {
LOGGER.info("getting orders: " + order.getId());
}
the foreach loop gets an exception:
EVERE: failed to lazily initialize a collection of role: com.aki.util.User.orders, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
Please note that I do not have this problem when running this from an webapp with some kind of OpenSessionInViewFilter.
One solution can be to make
User.ordersan eagerly fetched collection byEntity associations are lazily loaded by default. This means that the
ordersSet is actually just a proxy object that won’t get initialized until you invoke a method on it. This is good, because the associatedOrderobjects 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
OpenSessionInViewFilteryou 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
TransactionTemplateto wrap the code in your main method: