六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 7|回复: 0

Hibernate 一对多关联配置

[复制链接]

升级  37.4%

217

主题

217

主题

217

主题

进士

Rank: 4

积分
687
 楼主| 发表于 2013-2-3 11:03:34 | 显示全部楼层 |阅读模式
以Department和Employee为例。

Department类:
public class Department {private int id;private String name;// For one-to-many associationprivate 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-mappingpackage="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
因为em1和em2是两个瞬时对象。

解决办法是:
a. 在代码里加上s.save(em1); s.save(em2);
s.save(em1);s.save(em2);s.save(depart);
或者
b. 给set加上cascade="save-update"或者cascade="all"。
<hibernate-mapping<set name="employees" lazy="true" fetch="select" cascade="save-update"></hibernate-mapping>

2. 测试inverse属性:
set的inverse属性默认是false的,也就是由department维护关系。如果修改为true,执行上面的testSave方法,结果报错:Field 'depart_id' doesn't have a default value
这时关系由Employee维护,但是它没有机会(因为没有调用s.save(em1)和s.save(em2)),那么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在get方法执行的时候用两个SELECT语句把Department和Employee都查询出来。
b. 当fetch为join时:
   不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表