Hibernate关系映射其实就是将关系模型中实体之间的三种关系——多对一(一对多)、一对一、多对多映射成对象模型——Java这样的面向对象语言中相应的属性之间的关系。
多对一表示的是多个属性值对应于一个属性值,可以参考员工和部门之间的关系。在Java中就是员工中有部门这个属性。
参考Domain代码:
class Employee{ private Integer id; private String name; private Department depart; } class Department{ private Integer id; private String name; }
在多的那边,也就是Employee.hbm.xml中,在class元素下添加<many-to-one name=”depart” column=”depart_id” />。
案例:
public static void add() { //把对象模型-》关系模型 //当你获取一个session ,就会让hiberate去读取 //hibernate.cfg.xml,这就会加载对象映射文件,从而完成创建 Session session=null; Transaction ts=null; try { session=HibernateUtil.getThreadLocalSession(); ts=session.beginTransaction(); //添加一个记录 Department d1=new Department(); d1.setName("财务部"); Employee e1=new Employee(); e1.setName("zs"); e1.setDepartment(d1); Employee e2=new Employee(); e2.setName("ls"); e2.setDepartment(d1); // 可以先保存员工在保存部门,不过会多产生一些SQL语句 session.save(d1); session.save(e1); session.save(e2); ts.commit(); } catch (Exception e) { e.printStackTrace(); if(ts!=null){ ts.rollback(); } // TODO: handle exception }finally{ if(session!=null&&session.isOpen()){ session.close(); } } }
一对多表示的是一个属性值对应于多个属性值,可以参考部门和员工之间的关系。在Java中就是部门有员工这个集合属性。
参考Domain代码:
class Department{ private Integer id; private String name; private Set<Employee> emps; } class Employee{ private Integer id; private String name; private Department depart; }
<set name=”emps”> <key column=”depart_id”/> <one-to-many class=”Employee”/> </set>
案例:
public static void main(String[] args) { // TODO Auto-generated method stub //通过获取一个sesion,让hibernate框架运行(config->加载hibernate.cfg.xml) Session s=null; Transaction tx=null; try { //我们使用基础模板来讲解. s=HibernateUtil.getCurrentSession(); tx=s.beginTransaction(); //查询所有1号部门的学生 //String hql="from Student where dept.id=1"; //方法2 /* Department department1=(Department) s.get(Department.class, 3); //取出该部门的学生 Set<Student> stus= department1.getStus(); for(Student ss: stus){ System.out.println(ss.getName()); }*/ //添加学生 Department department=new Department(); department.setName("业务部门"); Student stu1=new Student(); stu1.setName("zs"); Student stu2=new Student(); stu2.setName("ls"); Set sets=new HashSet<Student>(); sets.add(stu1); sets.add(stu2); department.setStus(sets); // 要配置<set name="stus" cascade="save-update">才能级联保存 s.save(department); tx.commit(); } catch (Exception e) { if(tx!=null){ tx.rollback(); } }finally{ if(s!=null && s.isOpen()){ s.close(); } } }
PS:在Hibernate开发中,一对多和多对一一般是并存的,也就是存在一对多关系就会存在多对一关系,反应在Java代码中就是,一的那边有一个集合属性,里面放的是多的那边的对象,多的那边有一个一的对象属性。这样做的话,能够实得HQL查询起来特别方便,但是有一个懒加载的问题,这个问题在之后的博客中会讲到。
一对一表示的是一个属性值对应于一个属性值,可以参考人和身份证编号之间的关系。在Java中就是一个人只对应一个身份证编号。
参考Domain代码:
class Person{ private Integer id; private String name; private IdCard idCard; } class IdCard{ private Integer id; private java.util.Date useful_life; private Person person; }
PS:唯一的多对一关系,就变成了一对一关系了,采用domain->DB的开发方法时也会在Idcard表中生成外键。
多对多表示的是多个属性值对应于多个属性值,可以参考学生和课程之间的关系。因为多对多关系在操作和性能上不太理想,所以多对多映射使用较少,而是将多对多关系转化为一对多关系和多对一关系。
参考Domain代码:
class Student { private BigDecimal sid; private String sname; private Set studcourses = new HashSet(0); } public class Course { private BigDecimal cid; private String cname; private Short ccredit; private Set studcourses = new HashSet(0); } public class Studcourse { private BigDecimal stucourseid; private BigDecimal grade; private Student student; private Course course; }
级联(cascade)操作用来说明当对主对象进行某种操作时是否对其关联的从对象也做类似的操作。例如想删除选课系统中某个学生的时候,同时也自动把他选的课程都删除掉。
none,all,save-update,delete,lock,refresh,evict,replicate,persist,merge,delete-orphan (one-to-many) 。
配置文件:
<!-- 配置one-to-many关系 cascade="delete" 当删除该部门的时候(主对象,则级联删除它的学生从对象) --> <set name="stus" cascade="delete"> <!-- 指定Student类对应的外键 --> <key column="dept_id" /> <one-to-many class="Student" /> </set>
java代码:
//演示删除级联 //获取到某个部分 Department department=(Department) s.get(Department.class, 41); s.delete(department);
配置文件:
<set name="stus" cascade="save-update"> <!-- 指定Student类对应的外键 --> <key column="dept_id" /> <one-to-many class="Student" /> </set>
Java代码:
//添加学生 Department department=new Department(); department.setName("业务部门3"); Student stu1=new Student(); stu1.setName("zs"); Student stu2=new Student(); stu2.setName("小明6"); Set<Student> students=new HashSet<Student>(); students.add(stu1); students.add(stu2); department.setStus(students); s.save(department);
PS:一般对many-to-one,many-to-many不设置级联,在one-to-many(one的一方,比如Employee-Department),和one-to-one(主对象一方)中设置级联。
----------参考《韩顺平.hibernate从入门到精通》