关于多对一,一对多,一对一的解释见我之前写的博客mybatis(三)

 

  这里介绍的是hibernate中多对一,一对多,一对一的应用。

Dept实体

public class Dept {
    private Integer deptno;
    private String deptname;
}

  

Emp实体

public class Emp {
    private Integer empno;
    private String empname;

    //植入部门单个对象
    private Dept dept;
}

  

一. 多对一(many-to-one)

多对一的配置是在多的一方植入少的一方的实体

Dept.hbm.xml 文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.hibernate.mapping.entity">

    <class name="Dept" table="Dept" >

        <id name="deptno" column="DEPTNO">
            <generator class="native"/>
        </id>
        <property name="deptname" column="DEPTNAME"></property>
    </class>
</hibernate-mapping>

  这个配置文件没有任何特别之处。也没有关于多对一的配置

Emp.hbm.xml 文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.hibernate.mapping.entity">

    <class name="Emp" table="Emp" >

        <id name="empno" column="EMPNO">
            <generator class="native"/>
        </id>
        <property name="empname" column="EMPNAME"></property>

        <many-to-one name="dept" class="Dept" column="deptno"></many-to-one>

    </class>
</hibernate-mapping>

  该文件中出了常规属性的配置外,将植入的少的一方的实体

在多对一中就使用<many-to-one name="dept" class="Dept" column="deptno"></many-to-one>节点

name:指的是在实体类中植入的实体的属性名

Class:指的是该name的类型

column:指的是在底层数据库中关联另一张表的的列(例:在该环境中就表示与dept表中的deptno关联的列,该列在emp表中)

单测:

1.查询一号员工对应的部门

 @Test
    public void sel(){
        Session session = HibernateUtil.getSession();
        Emp emp = session.load(Emp.class, 1);


        System.out.println(emp.getEmpname());
        System.out.println(emp.getDept().getDeptname());


        HibernateUtil.closeSession();

    }

  结果:

2.保存员工到某个部门下

 @Test
    public void add(){
        Session session = HibernateUtil.getSession();

        Dept dept=new Dept();
        dept.setDeptno(1);

        Emp emp=new Emp();
        emp.setEmpname("hehehe");
        emp.setDept(dept);

        session.save(emp);

        HibernateUtil.closeSession();

    }

二.一对多

在少的一方植入一个HashSet集合

如:

public class Dept {
    private Integer deptno;
    private String deptname;

    private Set<Emp> emps=new HashSet<Emp>();
}

  在相应的配置文件中加入

 <set name="emps">
            <key column="deptno"></key>
            <one-to-many class="Emp"></one-to-many>
        </set>

  相应的:name:为植入得到set集合的属性名

      column:为该集合中的每一项与当前表的那一列有关系

      class:集合中的值是什么类型

单测:

 @Test
    public void sel(){
        Session session = HibernateUtil.getSession();

        String hql="from Dept";
        Query query = session.createQuery(hql);
        List<Dept> list = query.list();

        for (Dept dept:list){
            System.out.println(dept.getDeptname());

            for (Emp emp:dept.getEmps()){
                System.out.println(emp.getEmpname());
            }
            System.out.println("================");
        }

        HibernateUtil.closeSession();

    }

  结果:

 

 三. 一对一

与多对一非常相似,只是多的一方变为了一

这时你有两种方案来时实现该用法

1.假设每一个部门有且只有一个员工,来实现一对一只需要在  员工类和部门类中互相植入对方的属性即可,

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.hibernate.mapping.entity">

    <class name="Dept" table="Dept" >

        <id name="deptno" column="DEPTNO">
            <generator class="native"/>
        </id>
        <property name="deptname" column="DEPTNAME"></property>

        <one-to-one name="emp" class="Emp"></one-to-one>
       
    </class>
</hibernate-mapping>

      Emp.hbm.xml中的<many-to-one name="dept" class="Dept" column="deptno"   unique="true"></many-to-one>标签中设置"unique"="true"。即可

2.将<many-to-one name="dept" class="Dept" column="deptno"   unique="true"></many-to-one>节点改为

  <one-to-one name="demp" class="Demp"></one-to-one>

 

 四.控制属性

 Hibernate中控制属性主要有 cascade, inverse , order-by

1.cascade(级联)

Cascade取值:None,save-update,delete和all

   none:当Session操纵当前对象时,忽略其他关联的对象。它是cascade属性的默认值.

   Save-update:当通过Session的save()、update()及saveOrUpdate()方法来保存或更新当前对象时,级联保存所有关联的新建的瞬时状态的对象,并且级联更新所有关联的游离状态的对象。

   Delete:当通过Session的delete()方法删除当前对象时,会级联删除所有关联的对象。当通过Session的delete()方法删除当前对象时,会级联删除所有关联的对象。

   All:包含save-update,delete的行为。

  注意点:级联也就是说当我们保存持久化对象A的时候自动帮我们保存持久化对象B。而取值就是他的策略,决定了在什么时候会使用级联

 问题:cascade属性写在什么位置?

  解析:一对一或者多对一的时候,直接写在标签上,其他的写在set标签上。

2.inverse 

inverse属性指定了关联关系中的方向。

inverse设置为false,则为主动方,由主动方负责维护关联关系,默认是false 。

注意:inverse 决定是否把对对象中集合的改动反映到数据库中,所以inverse只对集合起作用,也就是只对one-to-manymany-to-many有效(因 为只有这两种关联关系包含集合,而one-to-onemany-to-one只含有关系对方的一个引用)。

Eg.测试代码如下:

tran = session.beginTransaction();

//准备一个Department对象

Department dept=new Department();

dept.setName("财务部");

//准备一个Employee对象

Employee emp=new Employee();

emp.setName("甄子丹");

//员工指定自己所属的部分

emp.setDept(dept);

dept.getEmployees().add(emp);

session.save(dept);

// 事务提交

tran.commit();

System.out.println("成功");

说明:如果我既给员工指定了自己所属的部门,又将员工添加到部门集合中。那么这个时候reverse不设置,生成以下sql

inverse设置为true,不负责维护关联关系

 

观察发现,其实第二条insert语句已经在员工表中指定了自己所属的部分,没有必要再向数据库发送一条update指令。

将inverse设置成true后,生成的语句如下图所示。

 

1.3 order-by

Hibernate如何对集合中的元素进行排序

解析:由于使用Hibernate后,生成SQL重任交给了Hibernate,所以Hibernate给我们留了一条绿色通道,可以让我们很容易的对集合中的数据进行排序。那就是使用order-by,使用order-by用于在数据库中对集合进行排序。

Eg.核心测试代码

Set集合设置如下:

 <set name="employees" cascade="save-update" inverse="true" order-by="id asc">   

       <key column="deptid"></key> 

       <one-to-many class="Employee"/> 

    </set>

注意:id是数据库表Employee中的列名,不是持久化类的属性名

List<Department> list = session.createQuery("from Department").list();

for (Department dept : list) {

for (Employee emp : dept.getEmployees()) {

System.out.println(emp.getId()+"\t"+emp.getName());

}

}

结果:

66 张三

67 李四

同一个部门下的员工编号按照升序排序

  

 

  

posted on 2017-12-28 17:16  读来过倒  阅读(229)  评论(0编辑  收藏  举报