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;
}