Я не могу понять, почему, но сессия Hibernate закрывается раньше, чем нужно, поэтому я не могу получить лениво загруженные списки.
В журналах показано, что сеанс закрывается сразу после hibernateTemplate.findByNamedParam () внутри DAO.
Когда я запускаю свое веб-приложение, я получаю следующую ошибку:
Mar 29, 2011 3:13:21 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Spring MVC Dispatcher Servlet] in context with path [/apps] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.communitydriven.apps.entities.Project.tags, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.communitydriven.apps.entities.Project.tags, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
at com.communitydriven.apps.managers.ProjectManager.getProject(ProjectManager.java:98)
at com.communitydriven.apps.controllers.ProjectController.getViewProject(ProjectController.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Мой DAO:
@Repository
public class ProjectDao implements IProjectDao {
private HibernateTemplate hibernateTemplate;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
...
/**
* {@inheritDoc}
*/
@Override
public Project getProject(Project project) {
// Validate required parameters
if ( (project.getId() == null) ) {
throw new NullPointerException("Missing required parameter: " +
project.toString());
}
// Parameters
List<String> paramNames = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
// Construct HQL
StringBuffer hql = new StringBuffer();
hql.append("from Project p ");
boolean whereUsed = false; // track of "where" clause has been used
// Filter by Id
if (project.getId() != null) {
whereUsed = DaoUtils.appendFilter(whereUsed, hql);
hql.append("p.id = :id ");
paramNames.add("id");
values.add(project.getId());
}
// Get list of matching projects
@SuppressWarnings("unchecked")
List<Project> projects =
hibernateTemplate.findByNamedParam(
hql.toString(),
paramNames.toArray(new String[paramNames.size()]),
values.toArray());
// Get unique result
Project projectResult = DataAccessUtils.uniqueResult(projects);
return projectResult;
}
}
Мой менеджер:
@Component
public class ProjectManager implements IProjectManager {
@Autowired
private IProjectDao projectDao;
...
/**
* {@inheritDoc}
*/
@Transactional
@Override
public ProjectMO getProject(Long projectId) {
Project project = new Project();
project.setId(projectId);
project = projectDao.getProject(project);
ProjectMO projectMO = new ProjectMO();
projectMO.setId(project.getId());
projectMO.setName(project.getName());
projectMO.setDescription(project.getDescription());
StringBuffer tags = new StringBuffer();
final String DELIMITER = ", ";
for (Tag tag : project.getTags()) {
tags.append(tag.getName() + DELIMITER);
}
projectMO.setTags(tags.toString());
return projectMO;
}
}
Сущность:
@Entity
@Table
public class Project {
private Long id;
private String name;
private String description;
private User submittedBy;
private List<Tag> tags;
public String toString() {
final String DELIMITER = ", ";
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName() + ": [");
sb.append("id: " + id).append(DELIMITER);
sb.append("name: " + name).append(DELIMITER);
sb.append("description: " + description).append("]");
return sb.toString();
}
// GETTERS AND SETTERS //
@Id
@Column
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToOne
@JoinColumn
public User getSubmittedBy() {
return submittedBy;
}
public void setSubmittedBy(User submittedBy) {
this.submittedBy = submittedBy;
}
@ManyToMany
@JoinTable(name="Projects_Tags",
joinColumns={@JoinColumn(name="project_id")},
inverseJoinColumns={@JoinColumn(name="tag_id")})
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}
Контекст моей базы данных:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=update
</value>
</property>
<property name="packagesToScan" value="com.communitydriven.apps.entities" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
</beans>