JPA Lazy Loading
hibernate, jakarta-ee, java, jpa
Solution
There are few alternatives you can use:
Use cascading persistence:
@OneToMany(fetch=FetchType.LAZY, mappedBy="user", cascade = {CascadeType.PERSIST})
List<OAuthLogin> oauthLogins;
In your Servlet do:
User user = new User(name);
user.setEmail(email);
OAuthLogin fbLogin = new OAuthLogin(user, OAuthProvider.FACEBOOK, "1501791394");
user.getOauthLogins().add(fbLogin) // this is enough assuming uni-directional association
userDAO.persist(user);
List<OAuthLogin> oauthLogins = user.getOauthLogins();
This should do, plus you have a single transaction and less JDBC calls.
This is helpful for that specific use case where it that specific Servlet method call.
pre-fetch collection in EJB
public User findById(int id, boolean prefetch) {
User entity = em.find(User.class, id);
if (prefetch) {
// Will trigger 1 or size JDBC calls depending on your fetching strategy
entity.getOauthLogins().size()
}
return entity;
}
Alternatively, Override fetch mode using a criteria
This is helpful for every case you want to fetch `OAuthLogin` collection with the `User` while preserving a `FetchType.LAZY` and avoid `LazyInitializationException` for that specific collection only.
Use Open Entity Manager in View Filter
Just Google it, you'll find plenty of examples
This will basically prevents `LazyInitializationException`, per every association fetched lazily, per each Entity application cross-wide
PS:
- If not using Spring why are you using `@Transactional` (by default even doesn't apply to `HttpServlet`)
- It had worked for WebLogic probably using some kind of tailored made solution
Problem
I have a problem with lazy loading property in JPA entity. I read many similar questions, but they are related to spring or hibernate and their answears are either not applicable or helpful. The application is JEE with JPA2.1 running on Wildfly application server. There are two entities, DAO session bean and servlet that puts it together: ``` @Entity @Table(name = "base_user") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") int id; @OneToMany(fetch=FetchType.LAZY, mappedBy="user") List<OAuthLogin> oauthLogins; } @Entity @Table(name = "oauth_login") public class OAuthLogin implements Serializable { @ManyToOne @JoinColumn(name="user_id", nullable=false) User user; } @Stateless(name = "UserDAOEJB") public class UserDAO { @PersistenceContext(unitName="OAUTHDEMO") EntityManager em; public User findById(int id) { User entity; entity = em.find(User.class, id); return entity; } } public class SaveUserServlet extends HttpServlet { @EJB UserDAO userDAO; @Transactional protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { User user = new User(name); user.setEmail(email); System.out.println("Persisting user " + user); userDAO.persist(user); OAuthLogin fbLogin1 = new OAuthLogin(user, OAuthProvider.FACEBOOK, "1501791394"); loginDAO.persist(fbLogin1); User user2 = userDAO.findById(user.getId()); List<OAuthLogin> oauthLogins = user2.getOauthLogins(); ``` When I run this code, it fails with: ``` org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: cz.literak.demo.oauth.model.entity.User.oauthLogins, could not initialize proxy - no Session org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572) org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212) org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:551) org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:140) org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294) cz.literak.demo.oauth.servlets.SaveUserServlet.doPost(SaveUserServlet.java:66) ``` I used very similar pattern with WebLogic/JPA1 and it ran smoothly. Any idea? Thanks PS. this is a JPA application, I do not have hibernate session etc.