【问题标题】:Java Standalone (Console) Application - org.hibernate.LazyInitializationException: could not initialize proxy - no SessionJava 独立(控制台)应用程序 - org.hibernate.LazyInitializationException:无法初始化代理 - 无会话
【发布时间】:2014-12-06 04:49:24
【问题描述】:

我搜索了所有 StackOverflow 网站和 Google,99.9% 的问题都与 Web 应用程序有关,但我没有找到任何 Java 独立应用程序(在 Linux 终端中运行 )的解决方案"java -jar myApp.jar") 用于经典异常 "org.hibernate.LazyInitializationException: could not initialize proxy - no Session"

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

我尝试了以下解决方案:

  1. Client 类中的 @Service@Transactional 注解,以及 Client 类调用的类中;
  2. @Service@Transactional(propagation = Propagation.REQUIRED) 注解在 Client 类和 Client 类中;
  3. @Service 切换到 @Component 并重试上述第 1 项和第 2 项;
  4. 尝试使用 TransactionTemplate 并在 TransactionCallback.doInTransaction() 方法中执行 client.start() 方法;
  5. 我已尝试从 Client 类中删除 @Service@Transactional 并从 Client 类调用的类中删除。

我已经尝试了所有这些,但我仍然得到 org.hibernate.LazyInitializationException: could not initialize proxy - no Session

代码中的cmets我也试过了。

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

Spring 配置由以下 XML 加载:

豆> ${hibernate.dialect}${hibernate.default_schema}${hibernate.show_sql}${hibernate.cache.use_second_level_cache}${hibernate.cache.use_query_cache}${hibernate.cache.region.factory_class}道具> 属性> 豆> 豆> 豆>

项目主类:

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 // // [...] } }

门面类(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 是应用程序外观(如上所述)。
  • 收件箱是另一个由客户端类调用的类
org.springframework.orm.hibernate4.HibernateSystemException:无法初始化代理 - 没有会话;嵌套异常是 org.hibernate.LazyInitializationException: could 不初始化代理 - 没有会话 在 org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216) 在 org.springframework.orm.hibernate4.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:57) 在 org.springframework.orm.hibernate4.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:44) 在 org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 在 org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 在 com.sun.proxy.$Proxy120.findLastPosition(未知来源) 在 com.mycompany.domain.facade.ABDomain.findLastPosition(ABDomain.java:832) 在 com.mycompany.domain.facade.ABDomain$$FastClassBySpringCGLIB$$f56e1d49.invoke() 在 org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 在 org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644) 在 com.mycompany.domain.facade.ABDomain$$EnhancerBySpringCGLIB$$4c071cee.findLastPosition() 在 com.mycompany.cpr.client.Inbox.updateLastPosition(Inbox.java:714) 在 com.mycompany.cpr.client.Inbox.processMessage(Inbox.java:604) 在 com.mycompany.cpr.client.Inbox$3.run(Inbox.java:934) 在 java.lang.Thread.run(Thread.java:745) 引起:org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话 在 org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) 在 org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) 在 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) 在 com.mycompany.domain.entity.Vehicle_$$_jvst374_1e.getId(Vehicle_$$$_jvst374_1e.java) 在 com.mycompany.domain.dao.impl.LastPositionDaoImpl.findLastPosition(LastPositionDaoImpl.java:34) 在 sun.reflect.GeneratedMethodAccessor1487.invoke(未知来源) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:483) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)

编辑 2:

收件箱是客户端类(主类)调用的类。收件箱没有注释,但我已经尝试过@Service @Transactional 或@Component @Transactional 注释。 我正在寻找Web项目中常用的OpenSessionInViewFilter之类的解决方案。

【问题讨论】:

  • 你在什么时候得到休眠异常?请以SSCCE 的形式发布相关代码以复制问题以及相关的堆栈跟踪。
  • @LuiggiMendoza 我已经编辑了问题并包含了堆栈跟踪。相关代码在 Client 类中。收件箱类有@Service@Transactional(propagation = Propagation.REQUIRED) 注释。但不管有没有这些注释,它都不起作用。
  • 您的堆栈跟踪表明异常出现在您尚未发布的 com.mycompany.cpr.client.Inbox.updateLastPosition 方法中,也没有您如何调用此方法。
  • 我在 DaoImpl (用@Repository 注释)中获得了 Vehicle (它是一个实体),但我尝试在另一个类(Inbox 类)中访问@ManyToOne 字段(例如vehicle.getOwner()) ,没有注释,但我已经尝试过@Service @Transactional 和@Component @Transactional 注释)。问题是当 Spring + Hibernate 创建一个代理然后我尝试访问@ManyToOne 字段时,我收到了错误org.hibernate.LazyInitializationException: could not initialize proxy - no Session。我正在寻找Web项目中常用的OpenSessionInViewFilter之类的解决方案。
  • 我反对这种解决方案,因为这意味着每个请求都应该打开一个数据库连接,而不是所有请求都需要连接到数据库,例如文件下载。基本上,问题是由通过会话获得的实体引起的,并且该实体已返回并且不在此会话中,然后您尝试访问延迟加载的字段但会话已关闭。因此,您有两个选择:1)在所有应用程序中使用相同的连接/会话(我们无法从您给定的代码中读取),2)使用 refresh 方法将对象同步到 1 级缓存。

标签: java spring hibernate console-application


【解决方案1】:

分析您的堆栈跟踪后,我看到调用了 TransactionInterceptor,因此唯一可能的解释是,如果您尝试初始化加载到与当前会话不同的会话中的 eneityt:

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

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

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

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

【讨论】:

  • 如果您阅读堆栈跟踪,Spring 已经在为该类创建代理。
  • 您需要添加完整的事务管理 Spring 配置。还有休眠属性。
  • @VladMihalcea 我的弹簧配置发布在我的问题中。我没有其他配置。问题是当我尝试访问与另一个实体(@OneToMany 或 @ManyToOne)关联的实体字段时。例如,当我尝试在另一种方法中执行vehicle.getOwner()(所有者是实体)时。
  • 也许该关联是在其他会话中获取的。你检查过我更新的答案吗?
  • @VladMihalcea 是的,我看到了你的答案。问题是我对所有 OneToMany 和 ManyToOne 关联使用延迟加载,因此主实体加载在一个线程中,我尝试在另一个线程中访问内部对象(延迟加载)。 Spring 和 Hibernate 正在按预期工作,因为它们必须在获取对象后关闭会话。
猜你喜欢
  • 1970-01-01
  • 2016-07-29
  • 2011-12-01
  • 2014-04-21
  • 2019-05-10
  • 2015-11-09
  • 2021-08-10
  • 1970-01-01
  • 2016-02-02
相关资源
最近更新 更多