Java hibernate非法尝试将集合与两个打开的会话关联

Java hibernate非法尝试将集合与两个打开的会话关联,java,hibernate,Java,Hibernate,我在学校的一个项目中使用了持久性,当我试图删除和更新对象时遇到了一个问题,所有其他查询都可以工作 例外情况是: Illegal attempt to associate a collection with two open sessions 我关闭我打开的每个会话 HibernateUtils代码 public class Hibernate { protected static final SessionFactory sessionFactory; private Session s

我在学校的一个项目中使用了持久性,当我试图删除和更新对象时遇到了一个问题,所有其他查询都可以工作

例外情况是:

Illegal attempt to associate a collection with two open sessions
我关闭我打开的每个会话

HibernateUtils代码

public class Hibernate
{
 protected static final SessionFactory sessionFactory;

 private Session session;

 static 
 {
  try 
  {
   // Create the SessionFactory from hibernate.cfg.xml
   sessionFactory = new Configuration().configure().buildSessionFactory();
   session
  } 
  catch (Throwable ex) 
  {
   // Make sure you log the exception, as it might be swallowed
   System.err.println("Initial SessionFactory creation failed." + ex);
   throw new ExceptionInInitializerError(ex);
  }
 }

 public void create(Object obj)
 {
  this.session = sessionFactory.openSession();
  session.getTransaction().begin();
  session.save(obj);
  session.getTransaction().commit(); 
  session.close();
 }

 public void refresh(Object obj)
 {
  this.session = sessionFactory.openSession();
  session.getTransaction().begin();
  session.refresh(obj);
  session.getTransaction().commit();
  session.close();
 }

 public void update(Object obj)
 {
  this.session = sessionFactory.openSession();
  session.getTransaction().begin();  
  session.saveOrUpdate(obj);
  session.getTransaction().commit();
  session.close();

 }
 public void delete(Object obj)
 {
  this.session = sessionFactory.openSession();
  session.getTransaction().begin();
  session.delete(obj);
  session.flush();
  session.getTransaction().commit();  
  session.close();
 }
 protected String protectString(String toProtect)
 {
  return (toProtect.replace("'", "''"));
 }

}
道人:

public class DAOPerson extends Hibernate
{

 public void remove(Person p)
 {
  if (p instanceof Student)
  {
   Student s = (Student)p;
   Set<persistenceClass.Class> set = s.getClasses();
   Iterator<persistenceClass.Class> it = set.iterator();
   while (it.hasNext())
   {
    persistenceClass.Class r = it.next();
    r.getStudents().remove(s);
   }
   p.getBirthCountry();
   p.getCountry();
   this.delete(p);
  }
  else
   this.delete(p);
}
公共类DAOPerson扩展了Hibernate
{
公共空间移除(p人)
{
如果(学生的p实例)
{
学生s=(学生)p;
Set=s.getClasses();
Iterator it=set.Iterator();
while(it.hasNext())
{
persistenceClass.Class r=it.next();
r、 getStudents()。删除(个);
}
p、 获取出生国();
p、 getCountry();
删除(p);
}
其他的
删除(p);
}
有关信息,我的学生映射文件为:

 <class name="persistenceClass.Person" table="T_PERSON">
  <id name="Id" column="PERSON_ID">
   <generator class="native" />
  </id>
  <property name="FirstName" column="PERSON_FIRST_NAME" not-null="true" />
  <property name="LastName" column="PERSON_LAST_NAME" not-null="true" />
  <property name="Type" column="PERSON_TYPE" not-null="true" />
  <property name="BirthDate" column="PERSON_BIRTH_DATE" />
  <property name="BirthCity" column="PERSON_BIRTH_CITY" />
  <property name="PhoneNumber" column="PERSON_PHONE_NUMBER" />
  <property name="MobileNumber" column="PERSON_MOBILE_NUMBER" />
  <property name="Mail" column="PERSON_MAIL" />
  <property name="Address" column="PERSON_ADDRESS_ADDRESS" />
  <property name="ZipCode" column="PERSON_ADDRESS_ZIPCODE" />
  <property name="City" column="PERSON_ADDRESS_CITY" />
  <property name="Image" column="PERSON_IMAGE" type="image" />
  <many-to-one name="Country" column="PERSON_ADDRESS_COUNTRY" class="persistenceClass.Country" />
  <many-to-one name="BirthCountry" column="PERSON_BIRTH_COUNTRY" class="persistenceClass.Country" />
  <many-to-one name="Civility" column="PERSON_CIVILITY" class="persistenceClass.Civility" />
  <many-to-one name="Sex" column="PERSON_SEX" class="persistenceClass.Sex" />
  <joined-subclass name="persistenceClass.Student" table="T_STUDENT">
   <key column="PERSON_ID" />
   <set name="Classes" table="T_CLASS_STUDENT" inverse="true" >
    <key column="PERSON_ID" />
    <many-to-many class="persistenceClass.Class" column="CLASS_ID" />  
   </set>
  </joined-subclass>
  <joined-subclass name="persistenceClass.Teacher" table="T_TEACHER">
   <key column="PERSON_ID" />
  </joined-subclass>
 </class>

和主映射文件:

<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/projet</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">10</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- Drop and re-create the database schema on start-up, also try with “update” to keep the previous values -->
<property name="hbm2ddl.auto">update</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<mapping resource="persistenceConfigurations/Person.hbm.xml"/>
<mapping resource="persistenceConfigurations/Country.hbm.xml"/>
<mapping resource="persistenceConfigurations/Civility.hbm.xml"/>
<mapping resource="persistenceConfigurations/Sex.hbm.xml"/>
<mapping resource="persistenceConfigurations/Formation.hbm.xml"/>
<mapping resource="persistenceConfigurations/Year.hbm.xml"/>
<mapping resource="persistenceConfigurations/Class.hbm.xml"/>
<mapping resource="persistenceConfigurations/Subject.hbm.xml"/>
<mapping resource="persistenceConfigurations/Room.hbm.xml"/>
<mapping resource="persistenceConfigurations/Lesson.hbm.xml"/>
</session-factory>
</hibernate-configuration>

org.gjt.mm.mysql.Driver
jdbc:mysql://localhost/projet
根
10
org.hibernate.dialogue.mysqlinnodbdialogue
更新
真的
我尝试了很多配置,但每次都有相同的例外,如果有人有想法,我想要

谢谢


抱歉,我的英语不好

会话不适用于一次呼叫并已关闭。使用实用程序类作为POJO的基础不是一个好主意

被删除的实体应使用从中检索到的相同会话,或至少在被删除之前在新会话上刷新


另外,通过删除依赖的“类”实体的迭代应该替换为级联删除。

我注意到您没有在person映射文件中定义
lazy=false
,因此我假设您正在对属性集使用lazy-loading属性。您说在调用REMOVE之前关闭了所有会话,然后现在,您可以访问
remove()中的属性
s.getClasses()
DAOPerson的方法而不抛出
lazyInitializationException
。如果您忘记在映射文件中提到
lazy=false
,那么我的观察值不算在内。如果不是这样,那么您肯定在某个地方打开了一个会话,该会话的人p(传递给DAOs remove方法)在这个方法的末尾,当你试图用另一个会话重新连接对象时,你会得到一个异常。

对于初学者来说,我认为重构你给类的概念命名(path persistenceClass.Class)是一个好主意。在java世界中,“Class”实际上是一个类。这可能会在将来造成一些混乱

我在DAOPerson代码中发现的一个问题是,它看起来很奇怪。我知道您正在尝试将当前学生从其类中删除,对吗?如果是,请在代码上尝试以下修补程序:

 public void remove(Person p)
 {
  if (p instanceof Student)
  {
   Student s = (Student)p;
   Set<persistenceClass.Class> set = s.getClasses();
   Iterator<persistenceClass.Class> it = set.iterator();
   while (it.hasNext())
    {
     persistenceClass.Class r = it.next();
     r.getStudents().remove(s);

     //now effectively removing the student from the class. 
     //this will update the class and its persistent set of students.
     this.update(r); 
    }
   }
   this.delete(p); //now remove the student (or whatever comes as argument)
 }

希望有帮助!

尝试使用
getCurrentSession()
而不是
openSession()
,并删除
session.close();
语句。

问题是由于其中一个映射中滥用了级联更新。下面是一个示例字段映射:

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = “user_id”)
public User getAuthor() {
return author;
}
删除cascade=CascadeType。所有这些都解决了问题。结论:小心使用cascade更新,因为它可能会给您带来麻烦。在业务逻辑需要时使用它。在下面的示例中,不需要它,因此从业务和编程两方面删除它都是一个好的决定


来源:

你能发布异常的完整堆栈跟踪吗?关于你的代码和项目设置的更多信息也会有帮助!!会话应该稳定运行,DAO+操作文件/控件的详细信息会帮助你处理接口吗?我不明白为什么人们坚持要在持久化单元上分层DAO。那就是说将一些固有的灵活性放在一个直夹套中。将持久性层放在一个直夹套中是您想要DAO的主要原因之一。其他原因是:构建特定于应用程序的持久性接口,从持久性层抽象出来,以便保存/删除等操作不依赖于DAO的细节它们的实现。JPA/Hibernate中的灵活性是危险的,不应该被滥用。顺便说一句,对我来说,它不是“灵活的”,而是一个复杂且很难掌握的API。
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = “user_id”)
public User getAuthor() {
return author;
}