Spring 3 JPA: исключение LazyInitializationException, несмотря на метод обслуживания @Transactional - PullRequest
0 голосов
/ 24 марта 2012

Я работаю с Spring 3, Hibernate 3.0.6 и JPA 2.

Я получаю LazyInitializationException:

Вот служба: @Service открытый класс ReportServiceImpl реализует ReportService {частный отчетDAO отчетDAO;частный 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>

1 Ответ

0 голосов
/ 06 ноября 2012

Если вы получаете исключение в view / jsp, то вам следует использовать открытый EntityManager в шаблоне представления. Все, что вам нужно сделать, это поместить фильтр OpenEntityManagerInViewFilter в web.xml http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.html

...