我试图从数据库中的对象进行简单加载,但出现错误“无法初始化代理-没有会话”,知道吗?谢谢
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; }
尝试添加@Transactional到validate方法:
@Transactional
@Override @Transactional(readOnly=true) public void validate(Object target, Errors errors) { ... }
发生的事情是,因为没有@Transactional注释,所以没有与该方法关联的会话,并且每个查询都将在其自己的会话中运行,该会话随后将立即关闭。
该方法session.load()始终返回一个代理,与之不同session.get()(请参阅此处,了解load与get之间的差异)。
session.load()
session.get()
因此,返回了代理,但是由于缺少@Transactional代理,因此立即关闭了创建代理的会话。第一次访问代理时,它的会话已关闭,因此我们收到“无会话”错误。
如果从更改load()为get(),则只能部分解决问题,因为如果在get之后尝试加载例如惰性初始化集合,则异常会再次发生。
load()
get()
添加@Transactional到业务方法将确保在方法调用期间存在相同的会话,并防止发生此错误和其他相关错误。