Spring 3 JPA: LazyInitializationException despite @Transacti



我正在使用Spring3、Hibernate 3.0.6和JPA2。

我得到了LazyInitializationException

这是ReportServiceImp服务:

@Service
    public class ReportServiceImpl implements ReportService {
        private ReportDAO reportDAO;
        private FieldDefDAO fieldDefDAO;
        private FieldDefService fieldDefService;
        /**
         * 
         */
        @Override
        @Transactional(propagation = Propagation.REQUIRED)
        public void updateReport(ReportTemplate reportTemplate, String[] fieldIds) {
            logger.entry(reportTemplate);
            try {
                ReportTemplate existingReport = reportDAO.findById(
                        reportTemplate.getId(), true);
                existingReport.setName(reportTemplate.getName());
                existingReport.setDepartment(reportTemplate.getDepartment());
                // set selected fields
                if (fieldIds != null) {
                    existingReport.removeReportFields();
                    for (String fieldId : fieldIds) {
                        FieldDef fd = fieldDefDAO.findById(Long.parseLong(fieldId), false);
                        // EXCEPTION THROWN HERE (
                        reportTemplate.addReportField(fd, i);
                    }
                }
                reportDAO.mergeState(existingReport, false);
            } catch (FocusDAOException fde) {
                throw new FocusServiceException(fde);
            }
            logger.exit();
        }
    }

实体:

@Entity
@Table(name = "REPORT_TEMPLATE")
@SQLDelete(sql = "UPDATE REPORT_TEMPLATE SET deleted = 1 WHERE REPORTTEMPLATE_ID = ? and OPTLOCK = ?")
@Where(clause = "deleted <> 1")
public class ReportTemplate extends Template {
    private Long id;
    private Set<ReportField> reportFields = new HashSet<ReportField>();
    /**
     * @return the id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "REPORTTEMPLATE_ID")
    public Long getId() {
        return id;
    }
    /**
     * @param id
     *            the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }
    /**
     * @return the reportFields
     */
    @OneToMany(mappedBy = "reportTemplate", cascade = { CascadeType.PERSIST,
            CascadeType.MERGE })
    public Set<ReportField> getReportFields() {
        return reportFields;
    }
    /**
     * @param reportFields
     *            the reportFields to set
     */
    public void setReportFields(Set<ReportField> reportFields) {
        this.reportFields = reportFields;
    }
    /**
     * 
     * @param field
     */
    @Transient
    public void addReportField(FieldDef field, int order) {
        ReportField rf = new ReportField(this, field, order);
        reportFields.add(rf);
        field.getReportFields().add(rf);        
    }
    /**
     * 
     */
    public void removeReportFields() {
        for (ReportField rf : reportFields) {
            rf.setReportTemplate(null);
            reportFields.remove(rf);
        }
    }
}
@Entity
@Table(name = "REPORT_FIELD", uniqueConstraints = @UniqueConstraint(columnNames = {
    "REPORTFIELD_ID", "FIELDDEF_ID", "DISPLAY_ORDER" }))
public class ReportField {
private Long id;
// @OrderColumn
private FieldDef field;
private ReportTemplate reportTemplate;
private int order;
/**
 * 
 */
public ReportField() {}
/**
 * 
 * @param reportTemplate
 * @param field
 * @param order
 */
public ReportField(ReportTemplate reportTemplate, FieldDef field, int order) {
    this.reportTemplate = reportTemplate;
    this.field = field;
    this.order = order;
}
/**
 * @return the id
 */
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "REPORTFIELD_ID")
public Long getId() {
    return id;
}
/**
 * @param id
 *            the id to set
 */
public void setId(Long id) {
    this.id = id;
}
/**
 * @return the field
 */
@ManyToOne
@JoinColumn(name = "FIELDDEF_ID", nullable = false)
public FieldDef getField() {
    return field;
}
/**
 * @param field
 *            the field to set
 */
public void setField(FieldDef field) {
    this.field = field;
}
/**
 * @return the report
 */
@ManyToOne
@JoinColumn(name = "REPORTTEMPLATE_ID", nullable = false)
public ReportTemplate getReportTemplate() {
    return reportTemplate;
}
/**
 * @param report
 *            the report to set
 */
public void setReportTemplate(ReportTemplate reportTemplate) {
    this.reportTemplate = reportTemplate;
}
/**
 * @return the order
 */
@Column(name = "DISPLAY_ORDER", nullable = false)
public int getOrder() {
    return order;
}
/**
 * @param order
 *            the order to set
 */
public void setOrder(int order) {
    this.order = order;
}

}

配置:

        <security:global-method-security
            pre-post-annotations="enabled" />
        <mvc:resources mapping="/resources/**" location="/resources/" />
        <bean id="jspViewResolver"
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass"
                value="org.springframework.web.servlet.view.JstlView" />
            <property name="prefix" value="/WEB-INF/jsp/" />
            <!-- <property name="suffix" value=".jsp" /> -->
        </bean>
        <bean id="tilesViewResolver"
            class="org.springframework.web.servlet.view.UrlBasedViewResolver">
            <property name="viewClass">
                <value>
                    org.springframework.web.servlet.view.tiles2.TilesView
            </value>
            </property>
            <property name="order" value="1" />
        </bean>
        <bean id="tilesConfigurer"
            class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
            <property name="definitions">
                <list>
                    <value>/WEB-INF/tiles/tiles.xml</value>
                </list>
            </property>
        </bean>
        <bean id="projectDS" class="org.apache.tomcat.jdbc.pool.DataSource"
            destroy-method="close"
            p:driverClassName="${driver.class.name}"
            p:url="${url}"
            p:initialSize="${initial.size}"
            p:maxActive="${max.active}"
            p:maxIdle="${max.idle}"
            p:minIdle="${min.idle}"
            p:testOnBorrow="true"
            p:validationQuery="SELECT 1"
            p:validationInterval="30000"
            p:timeBetweenEvictionRunsMillis="30000"
            p:removeAbandoned="true"
            p:removeAbandonedTimeout="60"
            p:logAbandoned="true"
            p:abandonWhenPercentageFull="75"
            p:jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer;SlowQueryReport(threshold=3000)"
        />
        <bean id="projectEMF"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="projectDS" />
            <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
        </bean>
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="projectEMF" />
            <property name="dataSource" ref="projectDS" />
        </bean>
        <bean id="jpaVendorAdapter"
            class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="SQL_SERVER" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
            <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect" />
        </bean>
        <bean id="validator"
            class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
        <bean id="auditLog" class="ca.utoronto.med.dc.focus.persistence.audit.AuditLog" />
        <bean
            class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    <!-- focus: Edit the package name below. -->
        <bean id="logoutHandlerBean"
            class="ca.utoronto.med.dc.focus.security.LogoutSuccessHandlerImpl" />
        <bean id="customAuthenticationFailureHandlerBean"
            class="ca.utoronto.med.dc.focus.security.AuthenticationFailureHandlerImpl" />
        <bean id="customAuthenticationSuccessHandlerBean"
            class="ca.utoronto.med.dc.focus.security.AuthenticationSuccessHandlerImpl" />
        <bean id="httpSessionEventListener"
            class="ca.utoronto.med.dc.focus.security.SimpleHttpSessionEventListenerImpl" />
        <mvc:annotation-driven />
        <task:annotation-driven />
        <tx:annotation-driven transaction-manager="transactionManager"/>
        <context:component-scan base-package="ca.utoronto.med.dc.*" />
    <!-- Uncomment the following section to enable Aspects -->
    <!-- <aop:aspectj-autoproxy /> 
        <bean id="authorizationMgr" class="ca.utoronto.med.dc.focus.aspect.AuthorizationMgr" />
    --> 
        <context:annotation-config
            transaction-manager="transactionManager" proxy-target-class="false" />
        <util:properties id="projectProperties" location="/WEB-INF/focus.properties" />
        <!--Bean to load properties file -->
        <bean id="placeholderConfig"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="/WEB-INF/focus.properties" />
        </bean>
        <!-- mail -->
    <!-- <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">        
            <property name="host" value="${mailserver.host}" />
            <property name="port" value="${mailserver.port}" />
            <property name="username" value="${mailserver.username}" />
            <property name="password" value="${mailserver.password}" />
        </bean> -->
        <!-- Configure the multipart resolver -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- one of the properties available; the maximum file size in bytes -->
            <property name="maxUploadSize" value="1000000"/>
        </bean>
    </beans>

如果您在view/jsp中获得异常,那么您应该在视图模式中使用openEntityManager。您所需要做的就是将过滤器OpenEntityManagerInViewFilter放在web.xml中http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.html

最新更新