如果我关闭会话,hibernate不会链接实体

时间:2013-09-13 19:00:31

标签: java hibernate jpa orm

我和学生之间有许多关联。

我的映射

Prepod:

@Entity
@Table(name = "prepod")
public class Prepod {

    private Long id;
    private String name;
    @Column
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    List<Student> students = new ArrayList<Student>();

    @ManyToMany(fetch=FetchType.EAGER)
    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Long getId() {
        return id;
    }

    public void setId(Long i) {
        id = i;
    }[/code]

学生:

@Entity
@Table(name = "Student")
public class Student {

    private Long id;
    private String name;
    private Long age;
    private List<Prepod> prepods = new ArrayList<Prepod>();

    @ManyToMany(mappedBy = "students",fetch=FetchType.EAGER)
    public List<Prepod> getPrepods() {
        return prepods;
    }

    public void setPrepods(List<Prepod> prepods) {
        this.prepods = prepods;
    }

    public Student() {
        name = null;
    }

    public Student(Student s) {
        name = s.getName();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Long getId() {
        return id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    @Column(name = "age")
    public Long getAge() {
        return age;
    }

    public void setId(Long i) {
        id = i;
    }

    public void setName(String s) {
        name = s;
    }

    public void setAge(Long age) {
        this.age = age;
    }
}

我有两个使用我的模型的变体调用代码。

第一个变种:

Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        Prepod prepod = (Prepod) session.get(Prepod.class, 1l);
        Student student = (Student) session.get(Student.class, 1l);
        session.getTransaction().commit();
        session.flush();
        session.close();
        List<Student> students = new ArrayList<Student>();
        students.add(student);

        List<Prepod> prepods = new ArrayList<Prepod>();
        prepods.add(prepod);

        prepod.setStudents(students);
        student.setPrepods(prepods);

        session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.update(student);

        session.getTransaction().commit();
        session.close();

适当的休眠日志:

Hibernate: select prepod0_.id as id1_1_1_, prepod0_.name as name2_1_1_, students1_.prepods_id as prepods1_1_3_, student2_.id as students2_2_3_, student2_.id as id1_0_0_, student2_.age as age2_0_0_, student2_.name as name3_0_0_ from prepod prepod0_ left outer join prepod_Student students1_ on prepod0_.id=students1_.prepods_id left outer join Student student2_ on students1_.students_id=student2_.id where prepod0_.id=?
Hibernate: select student0_.id as id1_0_1_, student0_.age as age2_0_1_, student0_.name as name3_0_1_, prepods1_.students_id as students2_0_3_, prepod2_.id as prepods1_2_3_, prepod2_.id as id1_1_0_, prepod2_.name as name2_1_0_ from Student student0_ left outer join prepod_Student prepods1_ on student0_.id=prepods1_.students_id left outer join prepod prepod2_ on prepods1_.prepods_id=prepod2_.id where student0_.id=?
Hibernate: update Student set age=?, name=? where id=?

此日志显示hibernate仅更新学生实体。与prepod的链接不会更新。

我编写第二个变量代码调用,没有会话关闭:

 Prepod prepod = (Prepod) session.get(Prepod.class, 1l);
    Student student = (Student) session.get(Student.class, 1l);
    session.getTransaction().commit();
    session.flush();
//  session.close(); // first change
    List<Student> students = new ArrayList<Student>();
    students.add(student);

    List<Prepod> prepods = new ArrayList<Prepod>();
    prepods.add(prepod);

    prepod.setStudents(students);
    student.setPrepods(prepods);

   // session = HibernateUtil.getSessionFactory().openSession();//second change
    session.beginTransaction();
    session.update(student);

    session.getTransaction().commit();
    session.close();

适当的休眠日志:

Hibernate: select prepod0_.id as id1_1_1_, prepod0_.name as name2_1_1_, students1_.prepods_id as prepods1_1_3_, student2_.id as students2_2_3_, student2_.id as id1_0_0_, student2_.age as age2_0_0_, student2_.name as name3_0_0_ from prepod prepod0_ left outer join prepod_Student students1_ on prepod0_.id=students1_.prepods_id left outer join Student student2_ on students1_.students_id=student2_.id where prepod0_.id=?
Hibernate: select student0_.id as id1_0_1_, student0_.age as age2_0_1_, student0_.name as name3_0_1_, prepods1_.students_id as students2_0_3_, prepod2_.id as prepods1_2_3_, prepod2_.id as id1_1_0_, prepod2_.name as name2_1_0_ from Student student0_ left outer join prepod_Student prepods1_ on student0_.id=prepods1_.students_id left outer join prepod prepod2_ on prepods1_.prepods_id=prepod2_.id where student0_.id=?
Hibernate: insert into prepod_Student (prepods_id, students_id) values (?, ?)

此日志显示在此变体中,这些实体之间的hibernate更新链接。

你能解释一下我的例子之间的主要缺陷吗?

2 个答案:

答案 0 :(得分:0)

对处于托管状态的持久性实体所做的更改将变为持久性。这是JPA / Hibernate的全部内容。如果实体处于托管状态(由当前打开的会话加载而未分离),则下次会话刷新时更改将保持不变。如果你没有显式启动事务,那么hibernate将在自动提交模式下执行它。从概念上讲,更新实体与数据库事务边界无关。这些是持久性机制的实现细节,往往会通过抽象泄漏。

答案 1 :(得分:0)

关闭会话时,您的对象变为分离。 阅读本文以获取更多信息http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html