Java Standalone(控制台)应用程序 - org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话

时间:2014-10-10 22:58:07

标签: java spring hibernate console-application

我搜索了所有StackOverflow网站和Google,99.9%的问题是关于网络应用程序的,但我没有找到任何 Java独立应用程序的解决方案(在Linux终端中运行“java -jar myApp.jar”)对于经典异常“ org.hibernate.LazyInitializationException:无法初始化代理 - 无会话

我的项目使用的是Spring 4.0.7 + Hibernate 4.3.6.Final + Log4J 1.2.17 + BoneCP 0.8.0

我尝试了以下解决方案:

    客户端类中的
  1. @Service @Transactional 注释以及Client类调用的类;
  2. 客户端类中的
  3. @Service @Transactional(propagation = Propagation.REQUIRED)注释以及Client类的类;
  4. @Service 切换到 @Component 并重试上面的第1项和第2项;
  5. 尝试使用TransactionTemplate并在TransactionCallback.doInTransaction()方法中执行client.start()方法;
  6. 我尝试从Client类中删除 @Service @Transactional ,并从Client类调用的类中删除。
  7. 我已经尝试了所有这些并且我仍然获取org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话

    代码中的注释也是我尝试过的。

    重要提示:项目使用Facade类,其中包含应用程序使用的所有方法。

    Spring配置由以下XML加载:

    
        <beans>
            <context:annotation-config />
            <context:component-scan base-package="com.mycompany" />
            <context:property-placeholder location="classpath:persistence.properties" />
            <tx:annotation-driven transaction-manager="transactionManager" />
    
            <!-- BoneCP -->
            <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
                <property name="driverClass" value="${jdbc.driverClassName}"/>
                <property name="jdbcUrl" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
                <property name="idleConnectionTestPeriodInMinutes" value="60"/>
                <property name="idleMaxAgeInMinutes" value="240"/>
                <property name="maxConnectionsPerPartition" value="30"/>
                <property name="minConnectionsPerPartition" value="10"/>
                <property name="partitionCount" value="3"/>
                <property name="acquireIncrement" value="5"/>
                <property name="statementsCacheSize" value="100"/>
                <property name="releaseHelperThreads" value="3"/>
            </bean>
    
            <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="packagesToScan" value="com.mycompany.domain.entity" />
                <property name="hibernateProperties">
                    <props>
                        <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                        <prop key="hibernate.default_schema">${hibernate.default_schema}</prop>
                        <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                        <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                        <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                        <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
                        <!-- I have tried setting "current_session_context_class", but still getting "org.hibernate.LazyInitializationException: could not initialize proxy - no Session" -->
                        <!-- <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> -->
                    </props>
                </property>
           </bean>
    
           <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
              <property name="sessionFactory" ref="sessionFactory" />
              <property name="dataSource" ref="dataSource" />
           </bean>
    
            <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
                <property name="transactionManager" ref="transactionManager"/>
            </bean>
    
           <bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
    
            <bean id="client" class="com.mycompany.console.Client" />
        </beans>
    

    项目主要课程:

    
    
        package com.mycompany.console;
    
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        import org.springframework.stereotype.Service;
        import org.springframework.transaction.annotation.Propagation;
        import org.springframework.transaction.annotation.Transactional;
    
        @Service
        @Transactional(propagation = Propagation.REQUIRED)
        public class Client {
            private static final Logger logger = Logger.getLogger(Client.class);
    
            public static void main(String args[]) {
                ApplicationContext applicationContext = null;
    
                // Load Spring application context
                try {
                    applicationContext = new ClassPathXmlApplicationContext("springHibernateConfig.xml");
    
                    final Client client = applicationContext.getBean("client"); // Or applicationContext.getBean(Client.class)
    
        // Already tried using TransactionTemplate, but still getting "org.hibernate.LazyInitializationException: could not initialize proxy - no Session"
        //          TransactionTemplate transactionTemplate = (TransactionTemplate) applicationContext.getBean("transactionTemplate");
        //          transactionTemplate.execute(new TransactionCallback() {
        //              @Override
        //              public Object doInTransaction(TransactionStatus status) {
        //                  client.start(args);
        //                  return null;
        //              }
        //          });
                    client.start(args);
    
                } catch (Exception e) {
                    System.err.println("Error loading Spring application context: " + e.getMessage());
                    e.printStackTrace();
                    System.exit(1);
                }
            }
    
            private void start(String args[]) {
                // List, Save, Update, Delete entities
                // 
                // Calls Facade.instance().getUserById(1L), for example
                // 
                // [...]
            }
        }
    
    
    

    Facade类(ABDomain):

    
    
        package com.mycompany.domain.facade;
    
        @Service
        @Transactional(propagation = Propagation.REQUIRED)
        public class ABDomain {
    
            public static ABDomain instance() {
                // SpringUtil implements ApplicationContextAware
                return SpringUtil.getApplicationContext().getBean(ABDomain.class);
            }
    
            public User getUserById(Long id) {
                /*
                    UsuarioDao is an interface, and its 
                    implementation UsuarioDaoImpl extends AbstractHibernateDao
                */
                return Registry.getUserDao().findById(id);
            }
        }
    
    
    

    注册表类:

    
    
        package com.mycompany.domain.registry;
    
        @Component
        @Transactional
        public class Registry {
    
            private static ApplicationContext applicationContext;
    
            @Autowired(required = true)
            public Registry(ApplicationContext appContext) {
                applicationContext = appContext;
            }
    
            public static UserDao getUserDao() {
                return applicationContext.getBean(UserDao.class);
            }
        }
    
    
    

    编辑:

    添加堆栈跟踪以便更好地理解。

    注意:

    • ABDomain是应用程序Facade(如上所述)。
    • Inbox是另一个由Client类
    • 调用的类
    org.springframework.orm.hibernate4.HibernateSystemException: could not initialize proxy - no Session; nested exception is org.hibernate.LazyInitializationException: could 
    not initialize proxy - no Session
            at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216)
            at org.springframework.orm.hibernate4.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:57)
            at org.springframework.orm.hibernate4.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:44)
            at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
            at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
            at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
            at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
            at com.sun.proxy.$Proxy120.findLastPosition(Unknown Source)
            at com.mycompany.domain.facade.ABDomain.findLastPosition(ABDomain.java:832)
            at com.mycompany.domain.facade.ABDomain$$FastClassBySpringCGLIB$$f56e1d49.invoke()
            at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
            at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
            at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
            at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
            at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
            at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
            at com.mycompany.domain.facade.ABDomain$$EnhancerBySpringCGLIB$$4c071cee.findLastPosition()
            at com.mycompany.cpr.client.Inbox.updateLastPosition(Inbox.java:714)
            at com.mycompany.cpr.client.Inbox.processMessage(Inbox.java:604)
            at com.mycompany.cpr.client.Inbox$3.run(Inbox.java:934)
            at java.lang.Thread.run(Thread.java:745)
    Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
            at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
            at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
            at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
            at com.mycompany.domain.entity.Vehicle_$$_jvst374_1e.getId(Vehicle_$$_jvst374_1e.java)
            at com.mycompany.domain.dao.impl.LastPositionDaoImpl.findLastPosition(LastPositionDaoImpl.java:34)
            at sun.reflect.GeneratedMethodAccessor1487.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:483)
            at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
            at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    
    

    编辑2:

    Inbox是一个由Client类(主类)调用的类。 Inbox没有注释,但我已经尝试过@Service @Transactional或@Component @Transactional注释。 我正在寻找像Web项目中常用的OpenSessionInViewFilter这样的解决方案。

1 个答案:

答案 0 :(得分:0)

在分析了你的堆栈跟踪之后,我看到了TransactionInterceptor被调用,所以唯一可能的解释是你尝试初始化一个在一个不同的会话中加载的能量而不是当前的一个:

所以,你调用这个方法:     在com.mycompany.domain.dao.impl.LastPositionDaoImpl.findLastPosition(LastPositionDaoImpl.java:34)

Vehicle实体是否在不同的线程/事务/会话中加载,然后在您拦截的消息中发送:

at com.mycompany.cpr.client.Inbox.processMessage(Inbox.java:604)

如果是这种情况,您需要在Producer事务中初始化所有想要的关联(获取Vehicle并发送它的那个)。