【发布时间】: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
我尝试了以下解决方案:
- Client 类中的 @Service 和 @Transactional 注解,以及 Client 类调用的类中;
- @Service 和 @Transactional(propagation = Propagation.REQUIRED) 注解在 Client 类和 Client 类中;
- 从 @Service 切换到 @Component 并重试上述第 1 项和第 2 项;
- 尝试使用 TransactionTemplate 并在 TransactionCallback.doInTransaction() 方法中执行 client.start() 方法;
- 我已尝试从 Client 类中删除 @Service 和 @Transactional 并从 Client 类调用的类中删除。
我已经尝试了所有这些,但我仍然得到 org.hibernate.LazyInitializationException: could not initialize proxy - no Session
代码中的cmets我也试过了。
重要提示:该项目使用 Facade 类,其中包含应用程序使用的所有方法。
Spring 配置由以下 XML 加载:
项目主类:
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 是应用程序外观(如上所述)。
- 收件箱是另一个由客户端类调用的类
编辑 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