JPA Lazy Loading
我在JPA实体中有延迟加载属性的问题。 我读了许多类似的问题,但它们与spring或hibernate有关,它们的问题不适用或有用。
该应用程序是JEE,在Wildfly应用程序服务器上运行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 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 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 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 oauthLogins = user.getOauthLogins();
这应该做,加上你有一个事务和更少的JDBC调用。
这对于特定Servlet方法调用的特定用例很有帮助。
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; }
或者, 使用条件覆盖提取模式
这对于您希望在保留FetchType.LAZY
同时使用User
获取OAuthLogin
集合并且仅针对该特定集合避免LazyInitializationException
每种情况都很有用。
在View Filter中使用Open Entity Manager
只是谷歌,你会发现很多例子
对于跨越每个实体应用程序的每个懒惰地获取的关联,这基本上会阻止LazyInitializationException
PS:
- 如果不使用Spring,为什么使用
@Transactional
(默认情况下甚至不适用于HttpServlet
) - 它曾适用于WebLogic,可能使用某种定制的解决方案
LazyInitializationException表示您在关联的会话关闭后访问延迟集合。
由于你的代码看起来很好,你的问题可能与JPA和Hibernate中的这个问题LazyInitializationException相同
您可以validation您的交易是在方法开头打开的吗?
要在JPA中初始化laze,你需要调用一个jar库并启动它,如果是maven或者手动的例子,如果你需要laze,在maven中使用jar
jar de.empulse.eclipselink 更多信息 http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving/Static_Weaving#Use_the_Maven_plugin
- 使用Hibernate @Index注释在DB上创建索引
- Java Hibernate和SQL Server中UUID的不同表示
- 在Hibernate 5中实现NamingStrategy(使自动生成的列名称为UPPERCASE)
- Spring,MySQL和Hibernate:如果系统在8小时内未使用,则会出现数据库错误
- HQL左连接:加入的路径
- 如何在Wildfly中部署时使用persistence.xml设置hibernate.hbm2ddl.auto
- java hibernate entity:允许通过id和object本身设置相关对象
- Spring应用程序在8小时后失去与MySql的连接。 如何正确配置?
- Hibernate有多对多关系集或列表?