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;
}
Try to add @Transactional
to the validate method:
@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.
The method session.load()
always returns a proxy, unlike session.get()
(see here for differences between load vs 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With