• SSH开发实践part3:hibernate继承映射


    0

      大家好。上次讲了关于hibernate中双向1-N的映射配置,可以参考:http://www.cnblogs.com/souvenir/p/3784510.html

      实际项目中,对象间的关系比较复杂,除了上次讲的相互关联以外,这次我们要讲的就是关于对象的继承。hibernate如何来通过配置完成对象的继承?

    1

      比如有一个父类person,然后两个对应的子类,一个是teacher,一个是student。教师和老师除了拥有person这个类所有的属性以外,还会有一些自己独特的属性。

      hibernate提供的映射方法有三种:

      A 一个子类对应一个表

      也就是说每个子类对对应新建一张表,里面的属性都会加上父类的属性,然后再分别加上自己的单独的属性

      这样做无疑是增加了许多冗余,所以不推荐。

      B 用一张大表来表示所有子类的属性集合

      比如父类有3个公共属性,teacher这个子类有2个单独属性,student有3个单独属性,那么我们需要创建一张表,把这8个属性全部包括在内

      然后在通过一个字段来区分这些对象实体具体属于那一个子类

      C 父类表存储公共属性,每一个字表存储自己单独的属性,然后通过唯一ID进行关联

    2  【用一张大表来表示所有子类的属性集合】

       还是用之前的employee对象来做演示,现在我们需要在employee下继承一个子类manager

        这个子类目前为了演示我们只添加一个单独的属性:部门

       来看看hibernate的配置文件:

      

    <hibernate-mapping package="com.souvenir.bean">
        <class name="Employee" table="Employee" discriminator-value="E">
            <!-- 映射标识属性 -->
            <id name="id" column="emp_id"
                type="int">
                <!-- 指定主键生成器策略 -->
                <generator class="identity"/>
            </id>
            
            <discriminator column="empType" type="string"></discriminator>
            
            <!-- 映射普通属性 -->
            <property name="name" type="string"/>
            <property name="password" type="string"/>
            <property name="age" type="int"/>
                          
        
            <!-- employee子类manager -->
            <subclass name="Manager"  extends="Employee"  discriminator-value="M">
                <property name="dept" type="string" length="50" column="dept_name"/>
            </subclass>
        </class>
    </hibernate-mapping>

      需要说明一下的是:

    • 这种方式是通过 subclass  关键字来完成子类的配置
    • 父类需要 discriminator  关键字类指定区分的字段
    • 所有子类添加 discriminator-value 属性来区分其对象(如果父类需要的话也可以加上)  

      下面我们来测试一下映射的效果,具体的测试代码我就不写了,大概就是保存几个manager和employee对象

      

      通过数据库中结果可以看出,前10个是employee对象,empType都是E

      最后一个是manager对象,empType为M

      这种方式可以看出也是有很多的冗余字段,对于employee来说没有dept_name属性,所以这个属性都为null

    3 【父类表存储公共属性,每一个字表存储自己单独的属性,然后通过唯一ID进行关联】

      这种情况下我们需要使用关键字 joined-subclass 来加入所有的子类,子类中除了需要配置单独的属性之外

      需要指定一个key,来与父类关联。(通过column属性)

      下面看一下上面修改的配置:

    <hibernate-mapping package="com.souvenir.bean">
        <class name="Employee" table="Employee" >
            <!-- 映射标识属性 -->
            <id name="id" column="emp_id"
                type="int">
                <!-- 指定主键生成器策略 -->
                <generator class="identity"/>
            </id>
            
            <!-- 映射普通属性 -->
            <property name="name" type="string"/>
            <property name="password" type="string"/>
            <property name="age" type="int"/>
            <!--  与manager的关联关系  -->
            <many-to-one name="manager" class="Manager" column="mgr_id" lazy="false"/>    
            
            <!-- 映射和Payment之间的关联关系 -->
            <set name="payments" inverse="true" lazy="false">
                <key column="emp_id" />
                <one-to-many class="Payment"/>
            </set>
        
            <!-- employee子类manager -->
            <joined-subclass name="Manager"  extends="Employee"  >
                 <key column="emp_id"></key>  
                <property name="dept" type="string" length="50" column="dept_name"/>
           </joined-subclass>
        </class>
    </hibernate-mapping>

      注意这里就不再需要 discriminator 配置了。

      下面看一下测试效果:(对了,测试代码都不用变)

      首先数据库中有了两个表,一个是employee,一个是manager

      

       

      这里可以看出,所有公共属性都存在了父表中,而子表只是存储了其需要的属性,二者通过emp_id来关联。

    4 继承对象的1-N关联

      像上面这种继承对象之间可否进行1-N的关联呢,答案是肯定的,而且在hibernate中的配置操作与一般的1-N没有什么差别。

      

    <hibernate-mapping package="com.souvenir.bean">
        <class name="Employee" table="Employee" >
            <!-- 映射标识属性 -->
            <id name="id" column="emp_id"
                type="int">
                <!-- 指定主键生成器策略 -->
                <generator class="identity"/>
            </id>
            
            <!-- 映射普通属性 -->
            <property name="name" type="string"/>
            <property name="password" type="string"/>
            <property name="age" type="int"/>
            <!--  与manager的关联关系  -->
            <many-to-one name="manager" class="Manager" column="mgr_id" lazy="false"/>    
            
            <!-- 映射和Payment之间的关联关系 -->
            <set name="payments" inverse="true" lazy="false">
                <key column="emp_id" />
                <one-to-many class="Payment"/>
            </set>
        
            <!-- employee子类manager -->
            <joined-subclass name="Manager"  extends="Employee"  >
                 <key column="emp_id"></key>  
                <property name="dept" type="string" length="50" column="dept_name"/>
                <set name="employees" inverse="true" lazy="false">
                    <key column="emp_id"/>
                    <one-to-many class="Employee"/>
                </set>
            </joined-subclass>
        </class>
    </hibernate-mapping>

      和我们上一讲的配置一样,1端通过set进行配置,N端都过many-to-one进行配置。

      需要补充一下的就是inverse这个属性, inverse=true的含义: 由双向关联另一方维护该关联,己方不维护该关联(只能进行查询操作)。

      在本例中,manager中有inverse属性,也就是说对于employee与manager的关联关系是交由employee进行维护,manager只能进行查询操作。

      

            Manager manager=mgrDao.get(11);
            
            for(int i=1;i<=5;i++){
                Employee emp=empDao.get(i);
                emp.setManager(manager);
                empDao.update(emp);
            }
            
            
            Set<Employee> emps= manager.getEmployees();
            for(Employee e:emps){
                System.out.println("------"+e.getName());
            }

      上面的测试代码,我们通过employee对象来配置其manager对象。

      然后通过manager来查找其对应的employee集合。

      

  • 相关阅读:
    返回到上一页的html代码的几种写法
    记一次网站服务器内存占用过多问题
    rpm命令数据库修复日志
    Linux vmstat命令实战详解
    innodb的innodb_buffer_pool_size和MyISAM的key_buffer_size
    mysql
    如何查看linux系统下的各种日志文件 linux 系统日志的分析大全
    /var/lock/subsys作用
    CentOS目录结构详解
    MySQL体系结构
  • 原文地址:https://www.cnblogs.com/souvenir/p/3795121.html
Copyright © 2020-2023  润新知