I'm starting to lose faith in Hibernate. It has caused me nothing but weird problems throughout the last few days.
Upon deleting an entity from the database I get the following exception:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:101)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:52)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:767)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:745)
at org.springframework.orm.hibernate3.HibernateTemplate$25.doInHibernate(HibernateTemplate.java:790)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:784)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:780)
at pl.edu.agh.adam.core.projects.dao.TagDAO.delete(TagDAO.java:98)
at pl.edu.agh.adam.core.projects.ProjectService.deleteTag(ProjectService.java:109)
at pl.edu.agh.adam.core.projects.web.TagPresenter.deleteTag(TagPresenter.java:97)
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 com.sun.el.parser.AstValue.invoke(AstValue.java:234)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:83)
at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:88)
at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:100)
at javax.faces.component.UICommand.broadcast(UICommand.java:120)
at javax.faces.component.UIData.broadcast(UIData.java:708)
at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:890)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:234)
at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1202)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:623)
at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:35)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:143)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:93)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
I've dug deep and tried numerous solutions from the hibernate forum, but still I don't know what's going on and where the sessions are opened. The conditions under which this problem occurs:
first: OpenSessionInViewFilter - I've asked about it here. Everything seemed to work fine, but the deleting stopped all of a sudden the following day and all I've done is - I've added a non-connected class to a non-connected package.
hibernateFilter org.springframework.orm.hibernate3.support.OpenSessionInViewFilter singleSession false sessionFactoryBeanName sessionFactory hibernateFilter *
second: three-tier architecture. Here are the classes and the JSF page:
@Entity
@Table(name = "tag")
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToMany(mappedBy = "tags", targetEntity = Project.class)
List<Project> projects = new ArrayList<Project>();
@Transient
public static final String PROP_ID = "id";
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "tag_id")
private Long id;
@Transient
public static final String PROP_NAME = "name";
@Column(name = "name", length = 25, unique = true)
private String name;
}
public class TagDAO extends HibernateDaoSupport implements ITagDAO {
@Override
public void create(Tag tag) {
getHibernateTemplate().save(tag);
}
@Override
public Tag getTag(String name){
Tag group = null;
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
criteria.add(Restrictions.eq("name", name));
List<Tag> tags = getHibernateTemplate().findByCriteria(criteria);
if ((tags != null) && (tags.size() > 0)) {
group = (Tag)tags.get(0);
}
return group;
}
@Override
public Tag getTag(Long id){
Tag group = null;
List<Tag> groups = getHibernateTemplate().find(
"from Tag where id = ?", id);
if ((groups != null) && (groups.size() > 0)) {
group = (Tag)groups.get(0);
}
return group;
}
@Override
public List<Tag> getTags(){
List<Tag> ret = getHibernateTemplate().find("from Tag");
System.out.println("Dao got "+ret.size()+" tags");
return ret;
}
@Override
public Integer getTagCount() {
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
criteria.setProjection(Projections.rowCount());
return (Integer)(getHibernateTemplate().findByCriteria(criteria).get(0));
}
@Override
public void delete(Tag group) {
getHibernateTemplate().delete(group);
}
@Override
public void update(Tag group) {
getHibernateTemplate().update(group);
}
@Override
public List<Tag> getTags(Integer first, Integer resultsPerPage,
String order, Boolean asc) {
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
if (asc){
criteria.addOrder(Order.asc(order));
}else{
criteria.addOrder(Order.desc(order));
}
return (List<Tag>)getHibernateTemplate().findByCriteria(criteria, first, resultsPerPage);
}
}
public class ProjectService implements IProjectService {
// Beans used by this service.
private IProjectDAO projectDao;
private ITagDAO tagDao;
@Override
public void createProject(Project project) throws AlreadyExistsException {
if (projectDao.getProject(project.getName()) != null) {
throw new AlreadyExistsException();
}
projectDao.addProject(project);
}
@Override
public List<Project> getProjects(Integer first, Integer howMany, String order,
boolean asc) {
return projectDao.getProjects(first, howMany, order, asc);
}
@Override
public Integer getProjectCount(){
return projectDao.getProjectCount();
}
@Override
public List<Project> getProjects() {
return projectDao.getAllProjects();
}
@Override
public void deleteProject(Long id) {
projectDao.removeProject(id);
}
@Override
public List<Tag> getTags() {
return tagDao.getTags();
}
@Override
public Tag getTag(String name){
return tagDao.getTag(name);
}
@Override
public void createTag(Tag tag) throws AlreadyExistsException {
if (tagDao.getTag(tag.getName()) != null) {
throw new AlreadyExistsException();
}
tagDao.create(tag);
}
@Override
public void deleteTag(Long id) {
tagDao.delete(tagDao.getTag(id));
}
@Override
public void updateTag(Tag tag) {
tagDao.update(tag);
}
}
@ManagedBean(name = "tagPresenter")
@RequestScoped
public class TagPresenter {
private List<Tag> tags;
private IProjectService projectService;
private Tag tag;
public void setTag(Tag tag) {
this.tag= tag;
}
public Tag getTag() {
return tag;
}
public TagPresenter() {
projectService = (IProjectService)ServiceFinder.getInstance()
.findBean("projectService");
tags = projectService.getTags();
}
private void refresh() {
tags = projectService.getTags();
}
public List<Tag> getTags() {
refresh();
return tags;
}
public void deleteTag() {
projectService.deleteTag(tag.getId());
}
}
finally the webpage:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:composition template="/templates/template.xhtml">
<ui:define name="head">
<title>Tags</title>
<link rel="stylesheet" type="text/css" href="#{facesContext.externalContext.requestContextPath}/styles/style.css"/>
</ui:define>
<ui:define name="content">
<h:form name="commandForm">
<p:dataTable var="tag" name="tagsList" value="${tagPresenter.tags}" paginator="true" rows="10" >
<p:column sortBy="#{tag.id}">
<f:facet name="header">
<h:outputText value="Id" />
</f:facet>
<h:outputText value="#{tag.id}" />
</p:column>
<p:column sortBy="#{tag.name}">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{tag.name}" />
</p:column>
<p:column>
<h:commandLink action="#{tagDisplayer.showTag}" value="Modify">
<f:setPropertyActionListener target="#{tagDisplayer.tag}" value="#{tag}"/>
</h:commandLink>
<h:commandLink action="#{tagPresenter.deleteTag}" value="Delete">
<f:setPropertyActionListener target="#{tagPresenter.tag}" value="#{tag}"/>
</h:commandLink>
</p:column>
</p:dataTable>
</h:form>
<p:messages id="deletingError" showDetail="true"/>
</ui:define>
</ui:composition>
`
Please help me resolve my problem. It looks as though I've gotten my share of each and every common pitfall of Hibernate. Please provide a thorough solution, because we can safely assume that I won't grasp any mild suggestions. Consider me a n00b thrown into an advanced project.