数据的多对一关系

来源:互联网 发布:智能音箱 知乎 编辑:程序博客网 时间:2024/05/16 17:07
实体是Employee和Department,它们之间是多对一的关系。

Department类:
Java代码  收藏代码
  1. public class Department {  
  2.     private int id;  
  3.     private String name;  
  4.   
  5.     public Department() {  
  6.     }  
  7.     public Department(String name) {  
  8.         this.name = name;  
  9.     }  
  10.     // getters and setters are omitted  
  11. }  
public class Department {    private int id;    private String name;    public Department() {    }    public Department(String name) {        this.name = name;    }    // getters and setters are omitted}


Employee类:
Java代码  收藏代码
  1. public class Employee {  
  2.     private int id;  
  3.     private String name;  
  4.     private Department department;  
  5.   
  6.     public Employee() {  
  7.     }  
  8.     public Employee(String name) {  
  9.         this.name = name;  
  10.     }  
  11.     // getters and setters are omitted  
public class Employee {    private int id;    private String name;    private Department department;    public Employee() {    }    public Employee(String name) {        this.name = name;    }    // getters and setters are omitted


Department.hbm.xml:
Xml代码  收藏代码
  1. <hibernate-mapping  
  2.     package=“com.john.myhibernate.domain”>  
  3.   
  4.     <class name=“Department”>  
  5.         <id name=“id”>  
  6.             <generator class=“native”/>  
  7.         </id>  
  8.         <property name=“name” length=“20” not-null=“true”/>  
  9.     </class>  
  10. </hibernate-mapping>  
<hibernate-mapping    package="com.john.myhibernate.domain">    <class name="Department">        <id name="id">            <generator class="native"/>        </id>        <property name="name" length="20" not-null="true"/>    </class></hibernate-mapping>


Employee.hbm.xml:
Xml代码  收藏代码
  1. <hibernate-mapping package=“com.john.myhibernate.domain”>  
  2.   
  3. <class name=“Employee”>  
  4.     <id name=“id”>  
  5.         <generator class=“native”/>  
  6.     </id>  
  7.     <property name=“name” length=“20” not-null=“true”/>  
  8.     <many-to-one name=“department” column=“department_id” class=“Department” fetch=“select”/>  
  9. </class>  
  10. </hibernate-mapping>  
<hibernate-mapping package="com.john.myhibernate.domain"><class name="Employee">    <id name="id">        <generator class="native"/>    </id>    <property name="name" length="20" not-null="true"/>    <many-to-one name="department" column="department_id" class="Department" fetch="select"/></class></hibernate-mapping>

many-to-one没有inverse属性,因为关系的维护是many的一方,不可能放弃对关系的维护。
many-to-one的lazy属性有三个取值:false, proxy, no-proxy。

1. 测试cascade属性:
Java代码  收藏代码
  1. public void testSaveCascade() {  
  2.     Session s = null;  
  3.     Transaction tx = null;  
  4.       
  5.     Department depart = new Department();  
  6.     depart.setName(”FCI”);  
  7.       
  8.     Employee em1 = new Employee(“John”);  
  9.     em1.setDepartment(depart);  
  10.       
  11.     Employee em2 = new Employee(“Lucy”);  
  12.     em2.setDepartment(depart);  
  13.       
  14.     try {  
  15.         s = HibernateUtil.getSession();  
  16.         tx = s.beginTransaction();  
  17.         s.save(em1);  
  18.         s.save(em2);  
  19.         tx.commit();  
  20.     } catch (HibernateException e) {  
  21.         tx.rollback();  
  22.         e.printStackTrace();  
  23.     } finally {  
  24.         if (s != null)  
  25.             s.close();  
  26.     }  
  27. }  
    public void testSaveCascade() {        Session s = null;        Transaction tx = null;        Department depart = new Department();        depart.setName("FCI");        Employee em1 = new Employee("John");        em1.setDepartment(depart);        Employee em2 = new Employee("Lucy");        em2.setDepartment(depart);        try {            s = HibernateUtil.getSession();            tx = s.beginTransaction();            s.save(em1);            s.save(em2);            tx.commit();        } catch (HibernateException e) {            tx.rollback();            e.printStackTrace();        } finally {            if (s != null)                s.close();        }    }

结果是报org.hibernate.TransientObjectException异常,因为没有保存Department实例。

可以加cascade属性,解决问题:
Xml代码  收藏代码
  1. <many-to-one name=“department” column=“department_id” class=“Department” fetch=“select” cascade=“save-update”/>  
<many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update"/>


2. 测试fetch
Java代码  收藏代码
  1. Session s = null;  
  2.   
  3. s = HibernateUtil.getSession();  
  4. Employee em = (Employee) s.get(Employee.class2);  
  5. System.out.println(em.getName());  
  6. System.out.println(em.getDepartment());  
   Session s = null;    s = HibernateUtil.getSession();    Employee em = (Employee) s.get(Employee.class, 2);    System.out.println(em.getName());    System.out.println(em.getDepartment());

查询语句如下:
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.department as department1_0_, employee0_.skill as skill1_0_, employee0_.sell as sell1_0_, employee0_.type as type1_0_ from Employee employee0_ where employee0_.id=?

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
因为fetch设置为select,所以对每个实体,都分别用一个SELECT语句

如果把fetch设置为join,也就是连表查询,只使用一个SELECT语句。如下:
Hibernate: select employee0_.id as id1_1_, employee0_.name as name1_1_, employee0_.department as department1_1_, employee0_.skill as skill1_1_, employee0_.sell as sell1_1_, employee0_.type as type1_1_, department1_.id as id0_0_, department1_.name as name0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.department=department1_.id where employee0_.id=?

3. 测试lazy
当fetch为select时,设置lazy为proxy或者no-proxy。
Xml代码  收藏代码
  1. <many-to-one name=“department” column=“department_id” class=“Department” fetch=“select” cascade=“save-update” lazy=“no-proxy”/>  
<many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update" lazy="no-proxy"/>

Java代码  收藏代码
  1. Session s = null;  
  2.   
  3. s = HibernateUtil.getSession();  
  4. Employee em = (Employee) s.get(Employee.class2);  
  5. s.close();  
  6. System.out.println(em.getName());  
  7. System.out.println(em.getDepartment());  
 Session s = null;    s = HibernateUtil.getSession();    Employee em = (Employee) s.get(Employee.class, 2);    s.close();    System.out.println(em.getName());    System.out.println(em.getDepartment());

结果是报org.hibernate.LazyInitializationException异常。
因为fetch为select,而且lazy为proxy或者no-proxy,所以开始仅仅查询Employee,当需要用SELECT语句查询Department时,Session已经关闭。

解决办法:
1. 设置lazy为false,hibernate会第一时间把Employee和Department查询出来。
   如果fetch为select,使用两个SELECT查询语句。
   如果fetch为join,使用一个SELECT连表查询语句。
2. 设置fetch为join,这时不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来。

转发了原创作者的文章,在此说声对不起了。重点内容**
原创地址:http://czj4451.iteye.com/blog/1625965**

0 0
原创粉丝点击