Department類:
- public class Department {
- private int id;
- private String name;
- public Department() {
- }
- public Department(String name) {
- this.name = name;
- }
- // getters and setters are omitted
- }
Employee類:
- 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:
- <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:
- <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屬性:
- 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屬性,解決問題:
- <many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update"/>
2. 測試fetch
- 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。
- <many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update" lazy="no-proxy"/>
- 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會進行連表查詢,把兩個實體都查詢出來。