Hibernate 一对多联系关系配置
Hibernate 一对多关联配置
以Department和Employee为例。
Department类:
Employee类:
Department.hbm.xml:
如果key的column属性不指定,则employee表中没有department的外键。
key的foreign-key属性指定key的名称。
如果one-to-many的class不指定,hibernate生成表时会报错。
Employee.hbm.xml:
1. 测试cascade属性
结果报错:org.hibernate.TransientObjectException
解决办法是:
a. 在代码里加上s.save(em1); s.save(em2);
或者
b. 给set加上cascade="save-update"。
2. 测试inverse属性:
set的inverse属性默认是false的,也就是由department维护关系。如果修改为true,执行上面的testSave方法,结果报错:Field 'depart_id' doesn't have a default value
Department不负责维护关系,那么employee表中的depart_id就会是null值,和not-null=true产生冲突。
3. 测试lazy, fetch属性
a. 当fetch为select时:
如果lazy为true,hibernate用SELECT语句查询出Department。当访问Employee时才用SELECT语句查询Employee,如果这时session关闭,会导致异常。
如果lazy为false,hibernate用两个SELECT语句同时把Department和Employee查询出来。
b. 当fetch为join时:
不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来
以Department和Employee为例。
Department类:
public class Department { private int id; private String name; // For one-to-many association private Set<Employee> employees; public Department() { } public Department(String name) { this.name = name; } // Getters and setters are omitted
Employee类:
public class Employee { private int id; private String name; 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"/> <set name="employees" lazy="true" fetch="select"> <key column="depart_id" not-null="true" foreign-key="slender"></key> <one-to-many class="Employee"/> </set> </class> </hibernate-mapping>
如果key的column属性不指定,则employee表中没有department的外键。
key的foreign-key属性指定key的名称。
如果one-to-many的class不指定,hibernate生成表时会报错。
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"/> </class> </hibernate-mapping>
1. 测试cascade属性
public void testSave() { Session s = null; Transaction tx = null; Department depart = new Department("FDI"); Employee em1 = new Employee("Jacy"); Employee em2 = new Employee("Neil"); Set<Employee> employees = new HashSet<Employee>(); employees.add(em1); employees.add(em2); depart.setEmployees(employees); try { s = HibernateUtil.getSession(); tx = s.beginTransaction(); s.save(depart); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally { if (s != null) s.close(); } }
结果报错:org.hibernate.TransientObjectException
解决办法是:
a. 在代码里加上s.save(em1); s.save(em2);
或者
b. 给set加上cascade="save-update"。
2. 测试inverse属性:
set的inverse属性默认是false的,也就是由department维护关系。如果修改为true,执行上面的testSave方法,结果报错:Field 'depart_id' doesn't have a default value
Department不负责维护关系,那么employee表中的depart_id就会是null值,和not-null=true产生冲突。
3. 测试lazy, fetch属性
public void testQueryLazy() { Session s = null; s = HibernateUtil.getSession(); Department depart = (Department) s.get(Department.class, 2); s.close(); System.out.println(depart.getName()); System.out.println(depart.getEmployees()); }
a. 当fetch为select时:
如果lazy为true,hibernate用SELECT语句查询出Department。当访问Employee时才用SELECT语句查询Employee,如果这时session关闭,会导致异常。
如果lazy为false,hibernate用两个SELECT语句同时把Department和Employee查询出来。
b. 当fetch为join时:
不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来