java - 具有相同标识符值的不同对象已与 session :. 关联,合并和 saveOrUpdate 均不起作用

标签 java hibernate jakarta-ee jpa

我有一个 GUI,其中显示了教师列表。其中两个由用户选择 - 他们将成为创建的新学校类(class)的类主任。 老师与类(class)的关系是n-m。

学校类(class):(它从其组继承其ID)

@Entity
@Table(name="school_classes")
@Cacheable(true)
public class SchoolClass extends Group{

    @ManyToMany(cascade=CascadeType.ALL, mappedBy="classes", fetch=FetchType.EAGER)
    private SortedSet<Teacher> teachers;

老师:

  @Entity
    @Table(name="teachers")
    @Cacheable(true)
    public class Teacher extends creator.models.school.Entity{
            // name etc

    @ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinTable(name="class_teachers",
    joinColumns = @JoinColumn(name="teacher_id", referencedColumnName="id"),
    inverseJoinColumns = @JoinColumn(name="class_id", referencedColumnName="id"))
    private SortedSet<SchoolClass> classes;

我尝试创建一个像这样的新类:

String className = request.getParameter("class_name");
String id1 = request.getParameter("class_teacher1");
String id2  = request.getParameter("class_teacher2");
Teacher t1 = DataRetrieveModule.getTeacher(id1);
Teacher t2 = DataRetrieveModule.getTeacher(id2);


Layout l = new Layout();
SchoolClass newClass = new SchoolClass(className);
newClass.setLayout(l);
newClass.addTeacher(t1);
t1.addClass(newClass);

newClass.addTeacher(t2);
t2.addClass(newClass);
DataInsertionModule.insert(newClass);

此语句DataRetrieveModule.getTeacher(id1) 打开一个 session ,通过 ID 检索教师并关闭它。 DataInsertionModule.insert(newClass) 还会打开一个 session ,调用 session.saveOrUpdate(newClass)。 (我也尝试过session.merge(newClass))

检索老师:

public static Teacher getTeacher(String id) {
        Session session = null;
        Teacher t = null;
        try{
            sessionFactory = MyFactory.getSessionFactory();
            session = sessionFactory.openSession();
            t = (Teacher) session.get(Teacher.class, Long.parseLong(id));

        }
        catch(Exception e) {
            System.out.println("in DAO:");
            e.printStackTrace();
            if(session!=null)
                session.close();
        }       
        finally{
            if(session!=null)
                session.close();
        }

        return t;
    }

数据插入:

public static void insert(Object o) {
        Session session = null;

        try 
        {
            sessionFactory = MyFactory.getSessionFactory();
            session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();

            session.save(o);
            tx.commit();

            System.out.println("insertion done");
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            if(session!=null)
                session.close();
        }
    }

但是插入永远不会起作用。 总有一个具有相同 id 的对象已存在。

a different object with the same identifier value was already associated with the session: [creator.models.school.Teacher#3]

我在 stackoverflow 上进行了搜索,并覆盖了我的所有业务对象继承的类中的 getHashCode 和 equals 方法:

@Override
public int compareTo(Entity o) {
    if(this.id < o.getId())
        return -1;
    else if(this.id > o.getId())
        return 1;
    return this.getClass().getName().compareTo(o.getClass().getName());
}

@Override
public boolean equals(Object o) {
    if(o instanceof Entity)
        return this.compareTo((Entity)o)==0;
    else return this.equals(o);
}

@Override
public int hashCode() {

    char[] bla = this.getClass().getName().toCharArray();
    int blue=0;
    for(char c:bla)
        blue = blue*10 + c;
    return (int) (id+blue);

}

此外,我尝试将 ManyToManyCascadeType 更改为 MERGE(再次恢复)。

目前,我在使用 session.get(..) 检索教师对象后合并了它们,因为检索会从数据库中获取大量数据。还有更多的 ..ToMany 关系。因此,可能会发生该调用导致两位老师都加载的情况。

public static Object merge(Object o) {
        Session session = null;
        Object returnVal = null;
        try 
        {
            sessionFactory = MyFactory.getSessionFactory();
            session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();
            returnVal = session.merge(o);
            tx.commit();

        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            if(session!=null)
                session.close();
        }
        return returnVal;
    }

.

Teacher t1 = DataRetrieveModule.getTeacher(id1);
Teacher t2 = DataRetrieveModule.getTeacher(id2);

t1= DataInsertionModule.merge(t1);
t2= DataInsertionModule.merge(t2);

因此我想,如果我将我的 get 方法返回的方法与另一位老师的 get 调用必须加载的方法合并,它应该可以工作。 (就像这里:http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/)但事实并非如此:(

这可能是因为同一个父类(super class)(Object 或我的实体类)的对象具有相同的 ID 吗?

请帮助我!

最佳答案

一种可能导致此错误的潜在情况是教师 1 和教师 2 的 ID 相同。由于您在每次获取之间关闭 session ,因此它们将被分离,并且您最终将加载两个不同的对象,它们都代表数据库中的同一行(它们具有相同的主键。)然后,当这些对象都将被重新附加时通过保存 SchoolClass 的 session ,Hibernate 将看到两个不同的对象,它们都代表数据库中的同一行,并且不知道哪一个代表要持久保存到数据库的正确状态。

不确定这里是否属于这种情况,但您应该运行调试器并检查 Teacher1 和 Teacher2 引用的对象的状态。

关于java - 具有相同标识符值的不同对象已与 session :. 关联,合并和 saveOrUpdate 均不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14751730/

相关文章:

java - 如何从 cassandraexecuteAsync() 方法调用方法抛出异常

java - if 语句导致 jar 无法运行

java - 如何在hibernate java中的createSQLQuery中使用ilike和%

java - 如何使用 HibernateDaoSupport 类在 Hibernate 中使用自定义 select 语句

java - 类型映射 MySQL 类型文本到 Java Hibernate

jakarta-ee - 添加到 ArrayList 时 Tomcat 上的运行时异常

java - 如何解决 Netbeans 中缺少的 Java EE 服务器库

java - Hibernate.update 是否需要重试?

java - 忽略 Mockito 中测试方法内部的无效方法

java - 如何使用JSP/Servlet将文件上传到服务器?