2011-06-14 147 views
1
@Entity 
@Table(name="Student") 
public class Student { 

    private String id; 
    private String firstName; 
    private String lastName; 
    private Set<Grade> grades = new HashSet<Grade>(); 

public void addGrade(Grade grade){ 
     grades.add(grade); 
    } 
    //rest of Getters and setters omitted 

    public void removeGrade(Grade grade){ 
    grades.remove(grade); 
    } 
@OneToMany(cascade = CascadeType.ALL,fetch=FetchType.LAZY,orphanRemoval=true) 
    @JoinColumn(name="s_id") 
    public Set<Grade> getGrades() { 
     return grades; 
    } 

等级:休眠 - 更新操作:

@Entity 
@Table(name="Grade") 
public class Grade { 
//all omitted 
} 

我有对象的学生,我想从收集的分级对学生的ID为“XYZ”

我取出一个现有等级在做以下操作:

String id = "xyz"; 
Session session = sessionFactory.getCurrentSession(); 
    Student student = (Student)session.load(Student.class,id); 
     student.removeGrade(grade); 
     session.update(student); 

一切完美的作品,但在SQL查询中,我看到了怪异的更新:

Hibernate: select student0_.id as id0_0_, student0_.FirstName as FirstName0_0_, student0_.LASTNAME as LASTNAME0_0_ from Student student0_ where student0_.id=? 
Hibernate: select grades0_.s_id as s4_0_1_, grades0_.id as id1_, grades0_.id as id1_0_, grades0_.FirstQuestion as FirstQue2_1_0_, grades0_.TotalGrade as TotalGrade1_0_ from Grade grades0_ where grades0_.s_id=? 
Hibernate: update Grade set s_id=null where s_id=? and id=? 
Hibernate: delete from Grade where id=? 

为什么要更新? update Grade set s_id=null where s_id=? and id=?

如何跳过它以提高性能?

回答

1

它似乎没有必要,它是在你的情况,因为你的级联类型是ALL。但是,有一些数据模型可以让孩子独立于另一个实体的多对多关系而存在。换句话说,如果您不希望删除成绩,如果您将学生关系从成绩级别中断,则更新是有意义的。在这种情况下,hibernate应该只取消外键值,但不要删除Grade行。

所以这就是发生了什么 - 当你通过从父集上的集合中删除孩子明确地破坏关系时,hibernate知道要更新子表以删除外键。当您的级联设置设置为'ALL'设置(它实际上可能是orphanRemoval = true)时,hibernate知道在不再有父级时删除实际的子行。我怀疑hibernate没有经过优化,因此它可以识别何时可以删除。

这可能是他们只是选择不实施的优化。

你可以阅读关于收集表现here。特别是第19.5节。

+0

对不起,但我没有得到它。为什么我有无用的更新?我想在关系中断时删除Grade对象,但我不想在删除之前更新。 – 2011-06-14 20:26:34

+0

@ danny.lesnik,我更新了我的答案。除非你能证明它是一个性能瓶颈,否则我不会担心它。重要的是要了解*为什么会发生。 – hvgotcodes 2011-06-14 21:37:43