org.hibernate.HibernateException: недопустимая попытка связать коллекцию с двумя открытыми сеансами - PullRequest
3 голосов
/ 21 июня 2010

После удаления объекта из базы данных я получаю следующее исключение:

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)

Я глубоко копался и пробовал многочисленные решения с форума гибернации, но все же я не знаю, что происходит и где открываются сессии. Условия, при которых возникает эта проблема:

Первый: OpenSessionInViewFilter - я спрашивал об этом здесь. Казалось, все работает нормально, но удаление внезапно прекратилось на следующий день, и все, что я сделал, - я добавил неподключенный класс в несвязанный пакет.

  <!-- Hibernate OpenSession Filter -->
  <filter>
   <filter-name>hibernateFilter</filter-name>
   <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
   <init-param>
    <param-name>singleSession</param-name>
    <param-value>false</param-value>
   </init-param>
   <init-param>
    <param-name>sessionFactoryBeanName</param-name>
    <param-value>sessionFactory</param-value>
   </init-param>
   </filter>
  <filter-mapping>
    <filter-name>hibernateFilter</filter-name>
   <url-pattern>*</url-pattern>
  </filter-mapping>

Второе: трехуровневая архитектура. Вот классы и страница JSF:

@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());
 }

}

наконец веб-страница:

<!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>
    </html>

Как возникает эта проблема и как я могу ее решить?

Ответы [ 3 ]

2 голосов
/ 12 мая 2012

Исправления для этого варьируются в широких пределах; это может быть вызвано такими проблемами, как

  • плохая обработка сеанса в конфигурации фреймворка
  • неверные настройки каскада, неправильные настройки постоянства
  • забывает об инициализации коллекции, хранящейся в отношении базы данных @ManyToOne.

Убедитесь, что тщательно проверили эти случаи в ваших конфигурациях отображения / гибернации - прежде чем тратить часы. : D

0 голосов
/ 07 июня 2012

Это может быть вызвано вызовом session.disconnect() вместо session.close().

0 голосов
/ 21 июня 2010

Ознакомьтесь с главой HibernateTemplate в документации по Spring. Взгляните на реализацию подхода обратного вызова для доступа к сеансу.

public void delete(final Tag group) throws Exception {
    HibernateCallback callback = new HibernateCallback() {
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            Object groupObj = session.load(Tag.class, group.getId());
            session.delete(groupObj);
            return null;
        }
    };
    getHibernateTemplate().execute(callback);
}

Если вышеприведенное не то, что вы ищете, вы все равно можете сделать традиционный подход, как упомянуто далее в документации Spring. При таком подходе не используйте HibernateTemplate для удаления объекта, а используйте Session из HibernateDaoSupport для обработки удаления.

public void delete(Tag group) throws Exception {
    Session session = getSession(false);
    Object groupObj = session.load(Tag.class, group.getId());
    session.delete(groupObj);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...