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 @Transactional
to the validate method:
尝试添加@Transactional
到验证方法中:
@Override
@Transactional(readOnly=true)
public void validate(Object target, Errors errors) {
...
}
What happens is that because there is no @Transactional
annotation, 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 @Transactional
the 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 @Transactional
to 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
到业务方法将确保在方法调用的持续时间内存在相同的会话,并防止发生这种和其他相关错误。