package dao.po; import java.util.Set; //部门类 public class Department{ private int id;//部门的ID private String name;//部门的名称 private Set<Employee> emps;//部门下的所有员工 (一对多关系) }
package dao.po; //员工类 public class Employee{ private int id;// 员工的ID private String name;// 员工的名称 private Department depart;//员工所在部门 (是多对一关系) }
XML:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="dao.po"> <class name="Department"> <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true" length="255" column="name"/> <set name="emps"> <!-- emps 是Department的一个属性 --> <key column="depart_id"></key> <!-- 通过员工表的 depart_id字段来关联,它是字段名 --> <one-to-many class="Employee"/> <!-- emps的类型是Employee --> </set> </class> </hibernate-mapping>
下面是重点:
<set name="emps"> <!-- emps 是Department的一个属性 -->
<key column="depart_id"></key> <!-- 通过员工表的 depart_id字段来关联,它是字段名 -->
<one-to-many class="Employee"/> <!-- emps的类型是Employee -->
</set>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="dao.po"> <class name="Employee"> <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true" length="255" column="`name`"/> <!-- 这里做多对一映射 --> <!-- name="depart"是Employee类的属性名 --> <!-- column="depart_id" 是表中字段名 --> <many-to-one name="depart" column="depart_id" not-null="true"></many-to-one> </class> </hibernate-mapping>
一对多 (一个部门 对 多个员工):查询部门(部门下有员工)
public static void main(final String[] args){ final Department de = query(2); final Set<Employee> set = de.getEmps(); //本部门的所有员工 for (final Employee em : set){ System.out.println(em.getName()); } } /** * 查询部门(部门下有员工) * @param id 部门ID * @return 部门对象 */ public static Department query(final int id){ Session session = null; try{ session = HibernateUtil.getSeesion(); final Transaction tx = session.beginTransaction(); final Department de = (Department) session.get(Department.class, id); //按ID查 //因为 部门的 "员工" 属性会懒加载, //在session关闭后,调用de.getEmps()无法取到员工信息 //所以这里用 Hibernate.initialize(de.getEmps()) 提前加载一下. Hibernate.initialize(de.getEmps()); tx.commit(); return de; }finally{ if (session != null){ session.close(); } } }
二、多对一(员工对部门)
package dao.po; // 员工类 public class Employee { private int id; // 员工的ID private String name; // 员工的名称 private Department depart; //员工所在部门, 是多对一关系 }
package dao.po; //部门类 public class Department { private int id; //部门的ID private String name; //部门的名称 }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="dao.po"> <class name="Employee"> <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true" length="255" column="`name`"/> <!-- 这里做多对一映射 --> <!-- name="depart"是Employee类的属性名 --> <!-- column="depart_id" 是表中字段名 --> <!-- 注意:下面没有非空 约束 , 很多情况,外键是有非空约束的, 一会后面说--> <!--column="depart_id" 中的depart_id是Employee对象的depart属性映射为Employee表中的depart_id字段--> <many-to-one name="depart" column="depart_id" ></many-to-one> </class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="dao.po"> <class name="Department"> <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true" length="255" column="`name`"/> </class> </hibernate-mapping>
保存员工 和 部门:
package dao; import org.hibernate.Session; import org.hibernate.Transaction; import dao.po.Department; import dao.po.Employee; //多对一的例子 , 多个员工 对 一个部门 public class Many2One{ public static void main(final String[] args){ add(); //添加两个员工, 一个部门 } //添加两个员工, 一个部门 public static void add(){ final Department depart = new Department(); //部门 depart.setName("技术部"); final Employee em1 = new Employee(); //员工 一 em1.setName("赵磊"); em1.setDepart(depart); final Employee em2 = new Employee(); //员工 二 em2.setName("陈加俊"); em2.setDepart(depart); Session session = null; try{ session = HibernateUtil.getSeesion(); final Transaction tx = session.beginTransaction(); session.save(depart); //先插入部门 session.save(em1); //后插入员工, 因为员工的外键是 部门 session.save(em2); tx.commit(); }finally{ if (session != null){ session.close(); } } } }
注意:保存的顺序:
第一种:
session.save(depart); //先插入部门
session.save(em1); //后插入员工, 因为员工的外键是 部门
session.save(em2);
输出的SQL:
Hibernate: insert into Department (`name`) values (?)
Hibernate: insert into Employee (`name`, depart_id) values (?, ?)
Hibernate: insert into Employee (`name`, depart_id) values (?, ?)
第二种:
session.save(em1); //先插入员工
session.save(em2);
session.save(depart); //后插入部门
输出的SQL:
Hibernate: insert into Employee (`name`, depart_id) values (?, ?)
Hibernate: insert into Employee (`name`, depart_id) values (?, ?)
Hibernate: insert into Department (`name`) values (?)
Hibernate: update Employee set `name`=?, depart_id=? where id=?
Hibernate: update Employee set `name`=?, depart_id=? where id=?
这里多了两句 update,要 注意:如果Employee.hbm.xml 中外键有非空约束,如下:保存时只能用" 第一种 "顺序,用了第二种,先插入员工,但depart_id字段为空,会异常,不能插入。
<many-to-one name="depart" column="depart_id" not-null="true"></many-to-one>
我们来查询一个员工,注意"部门":
//测试查询 public static void main(final String[] args){ final Employee em = query(7); //员工的部门 , 执行Hibernate.initialize()后, 在session关闭前就取得了部门. //若没有执行Hibernate.initialize(), 下面会抛异常. System.out.println(em.getDepart().getName()); } //查询一个员工出来 public static Employee query(final int id){ Session session = null; try{ session = HibernateUtil.getSeesion(); final Transaction tx = session.beginTransaction(); final Employee em = (Employee) session.get(Employee.class, id); //按ID查 //因为 员工的 "部门" 属性会懒加载, //在session关闭后,调用em.getDepart()无法取到部门信息 //所以这里用 Hibernate.initialize(em.getDepart()) 提前加载一下. //是em.getDepart() 而不是em Hibernate.initialize(em.getDepart()); tx.commit(); return em; }finally{ if (session != null){ session.close(); } } }
输出的SQL是:
Hibernate: select employee0_.id as id1_0_, employee0_.`name` as name2_1_0_, employee0_.depart_id as depart3_1_0_ from Employee employee0_ where employee0_.id=?