Hibernate org.hibernate.LazyInitializationException:懒得初始化角色集合:

Jåc*_*cob 6 java spring hibernate jpa jersey

我有下面提到的实体类,当我执行我的应用程序时,我得到以下异常.其他一些类似的问题并没有解决问题.

WARNING: StandardWrapperValve[jersey-serlvet]: PWC1406: Servlet.service()
for servlet jersey-serlvet threw exception
org.hibernate.LazyInitializationException: failed to lazily initialize 
a collection of role: test.entity.Dept.empDeptno, no session
or session was closed
at org.hibernate.collection.internal.AbstractPersistentCollection.
throwLazyInitializationException(AbstractPersistentCollection.java:393)
       at    org.hibernate.collection.internal.AbstractPersistentCollection.
throwLazyInitializationExceptionIfNotConnected
(AbstractPersistentCollection.java:385)
    at org.hibernate.collection.internal.AbstractPersistentCollection.
initialize(AbstractPersistentCollection.java:378) 
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

Emp Entity

@Entity
@Table(name = "EMP", schema = "SCOTT"
)
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Emp.findAllEmployees", query = "select e from Emp e left 
    join fetch e.deptNo order by e.empno desc")
})
public class Emp implements java.io.Serializable {
@Id
@Column(name = "EMPNO", unique = true, nullable = false, precision = 4,
scale = 0)
private short empno;
@ManyToOne
@JoinColumn(name = "DEPTNO", referencedColumnName = "DEPTNO")
private Dept deptNo;
Run Code Online (Sandbox Code Playgroud)

部门实体

@Entity
@Table(name = "DEPT", schema = "SCOTT"
)
@XmlRootElement
public class Dept implements java.io.Serializable {
@Id
@Column(name = "DEPTNO", unique = true, nullable = false, precision = 2,
scale = 0)
private short deptno;
@OneToMany(fetch=FetchType.LAZY,mappedBy = "deptNo")
private Set<Emp> empDeptno;
Run Code Online (Sandbox Code Playgroud)

DAOImpl

@Override
public List<Emp> findAllEmployees() {
  return getEntityManager().createNamedQuery("Emp.findAllEmployees",
 Emp.class).getResultList();
}
Run Code Online (Sandbox Code Playgroud)

泽西RESTful服务

 @Component
 @Path("/employee")
 public class EmployeeRestService {

 @Autowired
 EmployeeService employeeService;

 @GET
 @Produces({MediaType.APPLICATION_JSON})
 public List<Emp> getEmployees() {
 List<Emp> emp = new ArrayList<Emp>();
 emp.addAll(getEmployeeService().findAllEmployees());
 return emp;
 }
Run Code Online (Sandbox Code Playgroud)

Spring applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
    <!-- Data Source Declaration -->    
    <bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="jdbc/scottDS"/>   
    </bean>

    <context:component-scan base-package="net.test" />
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="DataSource" />
        <property name="packagesToScan" value="net.test" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value="${jdbc.dialectClass}" />
            </bean>
        </property>
    </bean>
    <bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />  
    <!-- Transaction Config -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>          
    <context:annotation-config/>
    <bean id="hibernateStatisticsMBean" class="org.hibernate.jmx.StatisticsService">
        <property name="statisticsEnabled" value="true" />
        <property name="sessionFactory" value="#{entityManagerFactory.sessionFactory}" />
    </bean>
</beans>
Run Code Online (Sandbox Code Playgroud)

Jåc*_*cob 9

我已通过在web.xml中添加以下内容来解决此问题

<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)

在这里这里礼貌

谢谢


isn*_*bad 5

问题是数据库/ JPA事务的范围只包含服务(我假设是无状态会话bean)并且不包含REST资源bean.

  1. Web服务器将请求分派给JAX-RS服务
  2. JAX-RS服务调用EJB无状态会话Bean
  3. 交易开始
  4. EJB无状态会话Bean从数据库加载数据(可能涉及其他bean)
  5. EJB无状态会话Bean返回结果
  6. 交易结束
  7. JAX-RS服务返回结果
  8. JAX-RS Producer创建XML List<Emp>并访问字段empDeptno.

因此,当Jersey从中获取Emp生成XML 的列表时,该事务已经被关闭.当现在empDeptNo导航该字段时,JPA会尝试延迟加载它,因为我们已经在有效的事务/会话之外而失败了.

您可以尝试通过使用无状态会话bean来扩展事务范围以包含Jersey REST资源bean.那么它可能如下:

  1. Web服务器将请求分派给JAX-RS服务
  2. 交易开始
  3. JAX-RS服务调用EJB无状态会话Bean
  4. EJB无状态会话Bean从数据库加载数据(可能涉及其他bean)
  5. EJB无状态会话Bean返回结果
  6. JAX-RS服务返回结果
  7. JAX-RS Producer创建XML List<Emp>并访问字段empDeptno.
  8. 交易结束

我不是100%肯定,也可能是第8步到第7步之前,因此交易可能会在生产者完成其工作之前关闭.如果是这样的话,这个解决方案就是错误的......

但我认为你应该只是尝试一下......