Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

org.hibernate.LazyInitializationException: could not initialize proxy - no Session?

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;
}
like image 929
darkZone Avatar asked Dec 06 '22 02:12

darkZone


1 Answers

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.

like image 78
Angular University Avatar answered Jan 19 '23 00:01

Angular University