我在JPA实体中的延迟加载属性有问题。我读过许多类似的问题,但它们与spring或hibernate有关,并且他们的后代不适用或没有帮助。
该应用程序是在Wildfly应用程序服务器上运行的JEE和JPA2.1。有两个实体,DAO会话bean和servlet将它们放在一起:
@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();
当我运行此代码时,它失败并显示:
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)
我对WebLogic / JPA1使用了非常相似的模式,并且运行平稳。任何的想法?谢谢
PS。这是一个JPA应用程序,我没有hibernate会话等。
您可以使用几种替代方法:
@OneToMany(fetch=FetchType.LAZY, mappedBy="user", cascade = {CascadeType.PERSIST}) List<OAuthLogin> oauthLogins;
在您的Servlet中执行以下操作:
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();
这样就可以了,加上您只有一个事务,并且JDBC调用更少。
这对于特定的Servlet方法调用的特定用例很有帮助。
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; }
或者,使用条件覆盖获取模式
这对于您想要在保留aOAuthLogin的User同时获取集合的每种情况都很有帮助,FetchType.LAZY并且避免LazyInitializationException仅针对该特定集合。
OAuthLogin
User
FetchType.LAZY
LazyInitializationException
只是Google,您会发现很多例子
基本上LazyInitializationException,这将防止每个懒惰获取的每个关联,每个跨整个实体的应用程序
PS:
@Transactional
HttpServlet