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.
LazyInitializationException means that you access a lazy collection AFTER the associated session had been closed.
As your code looks fine, your problem may be the same like in this question LazyInitializationException in JPA and Hibernate
Can you verify that your transaction is opened in the beginning of the method?
There are few alternatives you can use:
Use cascading persistence:
In your Servlet do:
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
Alternatively, Override fetch mode using a criteria
This is helpful for every case you want to fetch
OAuthLogin
collection with theUser
while preserving aFetchType.LAZY
and avoidLazyInitializationException
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-widePS:
@Transactional
(by default even doesn't apply toHttpServlet
)To initialize laze in JPA, you need to invoke a jar library and start it, if it is with maven or manual por example , if you need laze, use jar in maven
jar de.empulse.eclipselink More info http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving/Static_Weaving#Use_the_Maven_plugin