【问题标题】:LazyInitializationException with active transaction and connection open活动事务和连接打开的 LazyInitializationException
【发布时间】:2014-10-06 22:43:16
【问题描述】:

我知道这个问题已经被问过很多次了(已经在这里和其他网站上查看了大部分帖子),但我无法解决我的问题。

我的设置是:jpa 2 + hibernate 4 + spring 4 + primefaces + jboss eap 7

问题:我将一个惰性集合放入另一个 bean,但是当我在 bean 上调用 .size() 方法时,它会抛出“LazyInitializationException: failed to lazily initialize a collection of role: com.pe。 controlLines.data.model.Activity.activityRisks,无法初始化代理 - 没有 Session”

我确定我在 LazyInitializationException Within a @Transactional Methodhttp://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/ 之后得到了一个活跃的事务,所以我 100% 确定当时有一个事务正在运行。

我的实体类:

@Entity
public class Company {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long companyId;

    @Column
    private String name;

    @OneToOne(cascade={CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
    private Activity companieActivities;

    @OneToMany
    private Collection<SourceSupervision> sourceSupervisions;

和嵌套类

@Entity
@Indexed
public class Activity {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long activityId;

    @ManyToOne
    @JoinColumn(name="parentActivityId")
    private Activity parent;

    @Column
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    @Analyzer(definition = "searchtokenanalyzer")
    private String name;

    @Column
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    @Analyzer(definition = "searchtokenanalyzer")
    private String description;

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.REFRESH})
    private Collection<ActivityRisk> activityRisks = new ArrayList<ActivityRisk>();

    @ManyToMany(cascade={CascadeType.PERSIST, CascadeType.REFRESH})
    private Collection<Word> words;

    @ManyToMany
    private Collection<Rol> rolesForActivity;

bussines 委托是这样注释的(从页面控制器调用 bussines):

@Component
@Scope("session")
@Transactional
public class SystemConfigurationBussinesDelegate {

获得了对实体的引用的初始化,它执行得很好。 (这是来自 aboce 类)

private Company currentCompany;

    private Risk currentRisk;

    @PostConstruct
    public void init(){
        //((WordDAO)wordDAO).startIndexer();
        currentCompany = genericDAO.get(Company.class, 1l);
    }

但是在这个方法中

public List<Danger> getDangers(){

        List<Danger> returnValue = new ArrayList<Danger>();
        System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
        Hibernate.initialize(currentCompany.getCompanieActivities());
        currentCompany.getCompanieActivities().getActivityRisks().size();
        for( ActivityRisk aRisk : currentCompany.getCompanieActivities().getActivityRisks() ){
            Risk risk = aRisk.getRisk();
            if(risk == currentRisk){
                returnValue = new ArrayList<Danger>(aRisk.getDangers());
            }
        }
        return returnValue;
    }

sysout 返回 true,因此事务处于活动状态,我可以看到与数据库的打开连接,Hibernate.inicialize 工作正常,并且调用 currentCompany.getCompanieActivities().getActivityRisks().size();抛出异常。

可能是上下文或类似问题有问题吗?

我的弹簧配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-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/aop 
                        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                        http://www.springframework.org/schema/util 
                        http://www.springframework.org/schema/util/spring-util-2.5.xsd
                        http://www.springframework.org/schema/jdbc 
                        http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
                        http://www.springframework.org/schema/jee 
                        http://www.springframework.org/schema/jee/spring-jee.xsd">

    <context:component-scan base-package="com.pe.controlLines" />

    <context:annotation-config />
    <context:spring-configured />

    <aop:aspectj-autoproxy proxy-target-class="true"/>

    <jee:jndi-lookup id="myDataSource" jndi-name="java:/ControllinesDS"/>
    <!-- Data Source Declaration -->
    <!-- Session Factory Declaration <bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> -->
    <!-- Session Factory Declaration -->
    <bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
       <!-- <property name="packagesToScan">
            <list>
                <value>net.javabeat.spring.model</value>
            </list>
        </property>
        <property name="annotatedClasses">
            <list>
                <value>co.com.testTalos.model.Storage</value>
                <value>co.com.testTalos.model.Buyer</value>
                <value>co.com.testTalos.model.Preferences</value>
            </list>
        </property>-->
        <property name="packagesToScan">
            <list>
                <value>com.pe.controlLines.data.model</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.search.default.directory_provider">filesystem</prop>
                <prop key="hibernate.search.default.indexBase">C:/DEVELOPMENT/lucene/indexes</prop>


            </props>
        </property>
    </bean>

    <!-- Enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="txManager"/>

    <!-- Transaction Manager is defined -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="SessionFactory"/>
    </bean>

</beans>

【问题讨论】:

    标签: java spring hibernate jboss7.x jpa-2.0


    【解决方案1】:

    我认为您的问题与在 @PostConstruct 中调用事务方法有关。根据设计,spring tx 方面在 postconstruct 方法上/可能不活跃,因为并非所有 bean 都保证已完成构造。尝试搜索这个主题,我记得我也遇到过这个问题,但有很多有用的文章。

    从那时起,当我在 postconstruct 上需要 tx 时,我首选的替代方法是使用编程事务(参见 Spring TransactionTemplate 模式)使用 ContextRefreshedEvent。见下例:

    @Service
    public class MyService implements ApplicationListener<ContextRefreshedEvent> {
    
      public void onApplicationEvent(ContextRefreshedEvent event) {
        // This method will be executed at context startup or refresh
        // It is guaranteed all beans have finish constructing, hence
        // AOP tx is available
      }
      ...
    }
    

    【讨论】:

    • 你无法想象你让我多么开心......谢谢你,你的回答和一些 JUnit 测试让我解决了我所有的问题。
    猜你喜欢
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 2020-04-27
    • 1970-01-01
    • 2014-10-29
    • 2019-09-11
    相关资源
    最近更新 更多