Java 具有相同标识符值的不同对象已与会话关联

Java 具有相同标识符值的不同对象已与会话关联,java,hibernate,set,Java,Hibernate,Set,可能重复: 我得到以下错误: 具有相同标识符值的不同对象已与会话关联 我有两种类型的对象,课程和推荐时间表,其中包含一组课程。 以下是它们的xml定义: <hibernate-mapping> <class name="database.datatypes.Course" table="courses" lazy="false"> <id name="id" column="ID"> <generator class="ass

可能重复:

我得到以下错误:

具有相同标识符值的不同对象已与会话关联

我有两种类型的对象,课程和推荐时间表,其中包含一组课程。 以下是它们的xml定义:

<hibernate-mapping>
<class name="database.datatypes.Course" table="courses" lazy="false">
    <id name="id" column="ID">
         <generator class="assigned"/>
    </id>
    <property name="name" type="string"/>
    <property name="date"/>
</class>

那会有用的。(这当然不是真正的问题,只是一个简单的例子)

id是课程表的唯一键。每个id值只能使用一次。你们两门课的关系是m:n

当您对同一课程(相同id)使用不同的实例时,则尝试插入两个具有相同id的不同行。这无法工作。Hibernate会记住每个实例(实例,不是键值!),如果它已经保存,并且因为您使用了级联,所以在保存的时候Hibernate会查看哪些子实例还没有保存,如果您先保存
c1
,然后
c12
还没有保存,以后保存它会产生错误


解决方案:在推荐时间表的两个课程列表中插入相同的课程实例。无论如何,它们都是相同的课程。

最后,我只是简单地使用了merge()而不是save(),似乎它解决了问题,即使我有一组对象,而不仅仅是尝试使用普通对象。

,ID是如何分配的?ID来自外部,每门课程都会插入我无法控制的真实世界ID。(这是我的构造器中的第一个数字)这两个表不是同时填写的,我从一个来源获得课程,从另一个来源获得推荐的时间表。如果不使用DB课程替换每个推荐的课程表,是否就无法实现此功能?可能性1:不要级联操作。可能性2:从映射文件中删除
集合
,引入int类型的简单属性
courseId
,为方便起见,编写一个方法
readCourses()
,该方法在额外的查询中从不同查询中的一个推荐计划中读取课程。但是一个会话中不能有一个数据库实体的两个实例-如果您更改其中一个,另一个具有不同的值,那么哪一个会反映到数据库的情况?我实际上只在这里插入一次项,其余的是get操作。此外,我不会在操作之间保持会话打开。您认为这有什么帮助吗?每个会话只能将一个数据库实体附加到一个对象实例。这是Hibernate的设计决策。你不能绕开它。我注意到用合并而不是保存解决了我的问题。这样做有一个根本性的缺陷吗?如果在讨论结束时,你给自己写了一个答案,并把奖金给了帮助你的人,那么没有人愿意再次帮助你。不是你没有帮助我。。。但最后我用了别的东西。我想我应该根据我最后实际使用的答案来选择答案?@Johanna-自我接受的答案不会得到奖励,所以不要指责他。他的观点是正确的;理想情况下,被接受的答案应该是实际使用的答案。
<hibernate-mapping>
<class name="database.datatypes.RecommendedSchedule" table="recommended_schedules" lazy="false">
    <id name="id" column="ID">
         <generator class="increment"/>
    </id>
    <set name="courses" table="schedules_courses" cascade="save-update" lazy="false">
        <key column="course_id"/>
        <many-to-many class="database.datatypes.Course"/>
    </set>
    <property name="semester" type="string"/>
    <property name="path" type="string"/>
</class>
Session s = db.factory.openSession();
    Set<Course> set1 = new HashSet<>();
    Set<Course> set2 = new HashSet<>();
    Course c1 = new Course(104167L, "Algebra A");
    Course c2 = new Course(234114L, "Introduction to CS H and M");
    Course c3 = new Course(104012L, "Calculus 1 T");
    Course c4 = new Course(234145L, "Digital Systems");
    Course c12 = new Course(104167L, "Algebra A");
    Course c22 = new Course(234114L, "Introduction to CS H and M");
    Course c32 = new Course(104012L, "Calculus 1 T");
    Course c42 = new Course(234145L, "Digital Systems");
    set1.add(c1);
    set1.add(c2);
    set1.add(c3);
    set2.add(c12);
    set2.add(c22);
    set2.add(c32);
    set2.add(c42);
    RecommendedSchedule r1 = new RecommendedSchedule(set1, "General 3 years", "1");
    RecommendedSchedule r2 = new RecommendedSchedule(set2, "General 4 years", "1");
    Collection<RecommendedSchedule> col = new ArrayList<RecommendedSchedule>();
    Collection<Course> col2 = new ArrayList<Course>();
    col.add(r1);
    col.add(r2);
    col2.add(c12);
    col2.add(c22);
    col2.add(c32);
    col2.add(c42);

    Transaction t = s.beginTransaction();
    s.save(r1);
    s.save(r2);
    t.commit();
    s.close();
set2.add(c1);
set2.add(c2);
set2.add(c3);
set2.add(c4);