【问题标题】:JPA hibernate does not update entity object even by loading it from databse即使从数据库中加载,JPA hibernate 也不会更新实体对象
【发布时间】:2021-03-06 20:44:44
【问题描述】:

我有一个简单的例子来说明我的问题。有两个学生和三个科目。一开始student1有所有科目,student2没有科目。关系是一个学生和许多学科。

我正在尝试使用 jpa hibernate 将 subject1 从 student1 交换到 student2。数据库中出现事务提交更改后:主题表的外键student_id发生了更改,但在java中,即使我从数据库中加载student1,对象仍然有subject1。

@Entity
@Table(name = "STUDENTS")
public class Students {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ST_ID")
    private int id;


    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
    List<Subject> subjects = new ArrayList<>();
    //getters and setters....
}



@Entity
@Table(name = "SUBJECT")
public class Subject {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "SB_ID")
    private int id;

    @Column(name = "MARK")
    private int mark;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "ST_ID")
    private Students student;
    //getters and setter....
}

主要代码:

    public static void main(String[] args) throws Exception {
    
        EntityManager em = Persistence.createEntityManagerFactory("Test").createEntityManager();
//        em.getTransaction().begin(); //does not work
        Students student1 = getStudentById(1, em); //load student1 from database by id
        Students student2 = getStudentById(2, em); //load student2 from database by id
        
        Subject subject1 = getSubjectById(1, em); //load subject1 from database by id
        Subject subject2 = getSubjectById(2, em); //load subject2 from database by id
        Subject subject3 = getSubjectById(3, em); //load subject3 from database by id
        System.out.println("student1 subjects");
        for(Subject sb : student1.getSubjects()){
            System.out.println(sb.getId()); //prints subjects: 1,2,3
        }
        System.out.println("\nstudent2 subjects");
        for(Subject sb : student2.getSubjects()){
            System.out.println(sb.getId()); //prints no subjects
        }    
        //swap subject1 between student1 and student2
        subject1.setStudent(student2);
        student2.getSubjects().add(subject1);
        
        //save changes
        em.getTransaction().begin();
        em.persist(student2);
        em.persist(student1);
        em.persist(subject2);
        em.persist(subject1);
        //em.merge does't work
        //em.flush(); //doesn't work
        em.getTransaction().commit();
        
        student1 = getStudentById(1, em); //load student1 from database by id
        System.out.println("\nstudent1 subjects");
        for(Subject sb : student1.getSubjects()){
            System.out.println(sb.getId()); //and still student1 has subject1
        }
    
        student2 = getStudentById(2, em); //load student2 from databse by id
        System.out.println("\nstudent2 subjects");
        for(Subject sb : student2.getSubjects()){
            System.out.println(sb.getId()); //now student2 also has subject1
        }
    
        
    }
    
    public static Students getStudentById(int id, EntityManager em){
        Query query = em.createQuery("from entity.Students where ST_ID="+id);
        return (Students)query.getSingleResult();
    }
    public static Subject getSubjectById(int id, EntityManager em){
        Query query = em.createQuery("from entity.Subject where SB_ID="+id);
        return (Subject) query.getSingleResult();
    }

提交后的主题表如下所示。它显示 id 为 1 的科目现在有 id 为 2 的学生。

实体对象student1只有在我提交后em.refresh才会更新,但我不明白为什么我从数据库加载student1时需要使用refresh?而且我也不确定,刷新实体是好习惯吗?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    您必须了解 Hibernate 如果可能会从一级缓存或持久性上下文返回对象以保留对象身份。因此,即使您使用查询从数据库加载学生,它也只会返回您之前持久化的对象,因为它与持久化上下文相关联。

    当您想从数据库中重新加载状态时,您必须使用refreshdetach 然后进行查询。

    【讨论】:

    • 是的,我已经理解了这一点,但是非常感谢您的回答,因为我不确定。现在我正在考虑如何将这些知识应用到 spring Data 以刷新实体对象。如果您知道一些解决方案,我将非常感谢您的帮助
    • 我猜你正在使用视图反模式中的打开会话,因为它是 Spring Data 中的默认设置?在这种情况下,我建议您在想要重新加载之前提交的状态之前使用 entityManager.clear 清除持久性上下文。
    • 我不确定打开会话。我只是使用 Spring 数据中的 CrudRepos。你的意思是这样的吗? stackoverflow.com/questions/45491551/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 2012-01-25
    • 1970-01-01
    相关资源
    最近更新 更多