当前位置: 首页 > 知识库问答 >
问题:

Spring-HiberNate:非法尝试将集合与两个开放会话相关联

鲜于河
2023-03-14

我试图更新MySql数据库中的记录。更新时引发了以下异常

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.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at com.tcs.ignite.ih.spring.dao.UserDAOImpl.saveUpdateUserbean(UserDAOImpl.java:185)
at com.tcs.ignite.ih.spring.dao.UserDAOImpl.blockuser(UserDAOImpl.java:204)
at com.tcs.ignite.ih.spring.service.UserServiceImpl.blockUser(UserServiceImpl.java:187)
at com.tcs.ignite.ih.spring.controller.AdminHomeController.BlockUser(AdminHomeController.java:48)

我检查会话。它关闭在每个方法的最后块中。无法弄清楚出了什么问题。我能够毫无问题地使用其他方法插入更新操作,但只有保存更新用户豆方法抛出异常

UserDAOImpl:

import com.tcs.ignite.ih.hibernate.model.Userdetails;
import com.tcs.ignite.ih.hibernate.model.Userlog;
import com.tcs.ignite.ih.hibernate.model.Userrole;
import com.tcs.ignite.ih.spring.bean.LoginBean;
import com.tcs.ignite.ih.spring.util.LogFile;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;


@Repository
@Transactional
public class UserDAOImpl implements UserDAO {

@Autowired
private SessionFactory sessionFactory;

public SessionFactory getSessionFactory() {
    return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}


@Override
public Userdetails getUserDetails(String username) {
    Session session = getSessionFactory().openSession();
    Userdetails u = null;
    try {
        u = (Userdetails) getSessionFactory().openSession()
                .createCriteria(Userdetails.class)
                .add(Restrictions.eq("email", username)).uniqueResult();
    } catch (Exception e) {
        LogFile.log.error("UserDAO getuserDetails(): " + e.toString());
    } finally {
        if (session.isOpen()) {
            session.close();
        }
        return u;
    }
}

@Override
public boolean saveUpdateUserbean(Userdetails u) {

    Session session = getSessionFactory().openSession();
    Transaction tr = session.beginTransaction();
    boolean y = false;
    try {
        session.saveOrUpdate(u);
        tr.commit();
        y = true;
    } catch (Exception e) {
        tr.rollback();
        e.printStackTrace();
    } finally {
        if (session.isOpen()) {
            session.close();
        }
        return y;
    }
}

@Override
public boolean blockuser(String email) {
    Userdetails u = this.getUserDetails(email);
    return this.saveUpdateUserbean(u);
}
}

服务输入:

    import com.tcs.ignite.ih.hibernate.model.Userdetails;
import com.tcs.ignite.ih.hibernate.model.Userlog;
import com.tcs.ignite.ih.spring.bean.LogBean;
import com.tcs.ignite.ih.spring.bean.RegisterBean;
import com.tcs.ignite.ih.spring.bean.UserBean;
import com.tcs.ignite.ih.spring.bean.loadUserBean;
import com.tcs.ignite.ih.spring.dao.UserDAO;
import com.tcs.ignite.ih.spring.util.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserServiceImpl implements UserService {

@Autowired
UserDAO dao;

@Override
public boolean blockUser(String email) {
   return dao.blockuser(email);
}
}

applicationContext.xml:

<?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:aop="http://www.springframework.org/schema/aop"
   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.1.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location="classpath:jdbc.properties" />

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}"/>

<!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="packagesToScan" value="com.tcs.ignite.ih.hibernate.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean>
<tx:annotation-driven />
</beans>

我能够使用相同的配置执行所有数据库操作,但当我从serviceImpl调用块用户()方法时,它调用DAO方法,并且SaveupdateUserBean抛出上述异常?我错过了什么吗?

共有3个答案

郭弘盛
2023-03-14

如果你使用下面的代码,可能会出现问题

而不是使用 getSession() 如果你使用 '

< code>getHibernateTemplate()。getSessionFactory()。openSession(),导致同时打开两个会话。

苍温文
2023-03-14

使用内置会话工具:

sessionFactory.getCurrentSession()

不要自己手动开关它们。

集合正试图与两个会话相关联。此外SessionWorks虽然完全有效,但不是JPA的一部分。JPA依赖于EntityWorks

因为您将类定义为事务性的,所以您的方法不需要手动启动事务。从< code > saveourupdate 中删除此内容(以及对事务的任何引用)。

Transaction tr = session.beginTransaction();

事务通常在服务层而不是存储库上进行。因此,您可以将多个存储库/DAO调用包装在一个事务服务层方法中。

闻人伟
2023-03-14

Hibernate手册说:

如果您确定会话不包含具有相同标识符的持久实例,请使用update()。如果您想在任何时候合并您的修改而不考虑会话的状态,请使用merge()。换句话说,update()通常是您在新会话中调用的第一个方法,确保您分离的实例的重新附加是执行的第一个操作。

它对我的情况有所帮助。DAO:

public void updateUser(User user) throws UserException {
        sessionFactory.getCurrentSession().merge(user);
    }

POJO广告(一个用户有多个广告):

@OneToMany(mappedBy = "oUser", fetch = FetchType.LAZY)
public List<Ad> getAoAdList() {
    return aoAdList;
}
 类似资料:
  • 我使用Hibernate和Spring,我在执行以下代码时得到这个异常: 我已经阅读了一些关于Hibernate的会话管理,我有一种预感,这段代码的会话处理很差。举行两次公开会议的原因可能是什么?Hibernate API表示函数返回一个新的会话对象或现有的会话对象。在这种情况下,它从哪里获取现有会话对象?如果它创建了一个新的会话对象,那么处理所涉及的集合仍然可以吗? 任何帮助将不胜感激。提前感谢

  • 我在我的单元测试中看到了上面的错误,并且不知道如何纠正它。 我的单元测试类扩展了abstracttransactiondatasourcespringcontexttests并执行以下操作: 下面是我的规则组映射文件的一个片段。如您所见,RuleGroup封装了规则和属性集合,默认情况下这两者都是延迟加载的: 我的DAO类扩展了HibernateDaoSupport: 通过调试我的测试,在find

  • 在我当前的 spring 项目中,当我的应用程序尝试执行此方法时: 我得到了这个错误: 我的Dao类(插入方法的位置)是这样的: 我还尝试在Dao类中的insert、update和delete方法以及在服务类中使用它们的方法中添加注释@Transaction,但同样的问题也会发生。 有人能看出我做错了什么吗? ps.:我试图保存的实体类是:

  • 我在Hibernate4中使用JTA事务管理器。有人知道这个问题吗?在执行刷新时,我面临错误。 下面是我面临上述问题的一段代码。 XML:

  • 那么,除了避免使用jackson-hibernate-mapper进行测试之外,还有什么方法可以避免这个问题吗?使用DTO和Dozer代替domain object不被认为是一种解决方案(将来会这样做,但不是现在)。 提前致谢

  • 问题内容: 首先,我将Java EE与EntityManager和PrimeFaces一起使用Hibernate。 我有一个EJB模块(业务逻辑和域)和两个WAR模块(Jersey WS和JSF PrimeFaces)。 我决定在JSF WAR模块中初始化延迟集合,以避免延迟初始化异常。我不使用扩展实体管理器。 我得到: 我不明白 从数据库中获取初始化之前的一行时,必须有一个会话,不是吗?我以类似