Java org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22439306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
org.hibernate.LazyInitializationException: could not initialize proxy - no Session?
提问by darkZone
I am trying to make a simple load from an object from the DB, but i got the error "could not initialize proxy - no Session", Any idea ? Thanks
我正在尝试从数据库中的对象进行简单加载,但出现错误“无法初始化代理 - 没有会话”,知道吗?谢谢
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.jav a:167)
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
com.myapp.domain.User_$$_javassist_0.getLogin(User_$$_javassist_0.java)
com.myapp.validator.UserFormValidator.validate(UserFormValidator.java:34)
@Component
public class UserFormValidator implements Validator {
@Autowired
private UserDAO userDAO;
@Override
public boolean supports(Class<?> clazz) {
return UserForm.class.equals(clazz);
}
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public void validate(Object target, Errors errors) {
User user = (User)getUserDAO().findById(new Integer(1));
System.out.println ("User -> " + user.getLogin());
}
}
@Transactional
public class GenericDAOHibernateImpl <T, PK extends Serializable>
implements GenericDAO<T, PK> {
public GenericDAOHibernateImpl() {
super();
}
private Class<T> type;
@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
public GenericDAOHibernateImpl(Class<T> type) {
this.type = type;
}
public void saveOrUpdate(T object) {
getSession().save(object);
}
public Object findById(Serializable id) {
return getSession().load(type, id);
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}
<?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:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<context:property-placeholder location="/WEB-INF/jdbc.properties" />
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
<!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="classpath:hibernate.cfg.xml"
p:packagesToScan="com.myapp.domain"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${jdbc.driverClassName}"
p:jdbcUrl="${jdbc.url}"
p:user="${jdbc.username}"
p:password="${jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10"
/>
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
@Entity
@Table(name="USER")
public class User extends appEntity {
@Id
@Column(name = "USER_ID", unique = true, nullable = false)
private Integer id;
@Column(name = "LOGIN")
private String login;
@Column(name = "PASSWORD")
private String password;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
采纳答案by Angular University
Try to add @Transactionalto the validate method:
尝试添加@Transactional到验证方法中:
@Override
@Transactional(readOnly=true)
public void validate(Object target, Errors errors) {
...
}
What happens is that because there is no @Transactionalannotation, there is no session associated to the method, and each query will run in it's own session that is closed immediately afterwards.
发生的情况是,因为没有@Transactional注释,所以没有与该方法相关联的会话,并且每个查询都将在其自己的会话中运行,该会话随后立即关闭。
The method session.load()always returns a proxy, unlike session.get()(see here for differences between load vs get).
该方法session.load()总是返回一个代理,不像session.get()(请参阅此处了解load 与 get 之间的差异)。
So the proxy is returned, but due to the missing @Transactionalthe session that created the proxy is immediately closed. When the proxy is accessed the first time, it's session is closed so we get the 'no session' error.
所以代理被返回,但由于缺少@Transactional创建代理的会话立即关闭。第一次访问代理时,它的会话已关闭,因此我们收到“无会话”错误。
If you change from load()to get()that will only partially solve the problem, because if after the get you try to load for example a lazy initialized collection, the exception occurs again.
如果从改变load()到get(),这将只能部分解决问题,因为如果让在您尝试加载例如延迟初始化集合,异常再次发生。
Adding @Transactionalto the business method will ensure the presence of the same session for the duration of the method call, and prevent the occurrence of this and other related errors.
添加@Transactional到业务方法将确保在方法调用的持续时间内存在相同的会话,并防止发生这种和其他相关错误。

