• Hibernate继承映射多态关联


    把类之间的继承关系反应到数据库中,三种方法

    (1).只用一个表,子类的属性对应数据库表中额外的字段。使用<discriminator>和<subclass>

    以下例子中Delivery(投递)类的两个子类PostDelivery(邮递)和ExpressDelivery(快递),注意必须在父类中也加上discrminator-value否则报“Could not format discriminator value to SQL string...”错。注意<discriminator>在除id以外的其他子元素之前,否则解析xml文件出错。

     1 <class name="com.tazi.domin.Delivery" table="DELIVERY" discriminator-value="2">
    2 <id name="id" type="java.lang.Integer">
    3 <column name="ID"/>
    4 <generator class="identity"/>
    5 </id>
    6 <discriminator column="delivery_type" type="int"></discriminator>
    7 <property name="phone" type="string" column="phone"/>
    8 <property name="address" type="string" column="address"/>
    9 <property name="postcode" type="string" column="POSTCODE"/>
    10 <subclass name="com.tazi.domin.PostDelivery" discriminator-value="0">
    11 <property name="parcelNumber" column="PARCEL_NUMBER"></property>
    12 </subclass>
    13 <subclass name="com.tazi.domin.ExpressDelivery" discriminator-value="1">
    14 <property name="expressCompany" column="EXPRESS_COMPANY"></property>
    15 <property name="expressNumber" column="EXPRESS_NUMBER"></property>
    16 </subclass>
    17 </class>

    适用于在继承映射中总是需要多态查询,而且子类的属性相对比较少

    (2).每一个具体类一个表

    设置类Delivery为abstract在父类的class标签中也加上abstract="true",主键策略不能再使用identity,可以用increment或hilo.

     1     <class name="com.tazi.domin.Delivery" abstract="true">
    2 <id name="id" type="java.lang.Integer">
    3 <column name="ID"/>
    4 <generator class="increment"/>
    5 </id>
    6 <property name="phone" type="string" column="phone"/>
    7 <property name="address" type="string" column="address"/>
    8 <property name="postcode" type="string" column="POSTCODE"/>
    9 <union-subclass name="com.tazi.domin.PostDelivery" table="POST_DELIVERY">
    10 <property name="parcelNumber" column="PARCEL_NUMBER"></property>
    11 </union-subclass>
    12 <union-subclass name="com.tazi.domin.ExpressDelivery" table="EXPRESS_DELIVERY">
    13 <property name="expressCompany" column="EXPRESS_COMPANY"></property>
    14 <property name="expressNumber" column="EXPRESS_NUMBER"></property>
    15 </union-subclass>
    16 </class>

    例子1:单个子类的操作

    1         PostDelivery pDelivery=new PostDelivery();
    2 pDelivery.setPhone("13526356485");
    3 pDelivery.setAddress("北京西街15号");
    4 pDelivery.setPostcode("100080");
    5 pDelivery.setParcelNumber("8578");
    6 session.save(pDelivery);

    hql输出,它使用union将两个表连起来

     1 Hibernate: 
    2 select
    3 max(ids_.ID)
    4 from
    5 ( select
    6 ID
    7 from
    8 EXPRESS_DELIVERY
    9 union
    10 select
    11 ID
    12 from
    13 POST_DELIVERY
    14 ) ids_
    15 Hibernate:
    16 insert
    17 into
    18 POST_DELIVERY
    19 (phone, address, POSTCODE, PARCEL_NUMBER, ID)
    20 values
    21 (?, ?, ?, ?, ?)

    例子2:多态查询

    1 Query query=session.createQuery("from Delivery");//查询父类得到所有子类的信息
    2 List<Delivery> delivery=query.list();

    3 for(Delivery d:delivery)
    4 System.out.println(d.getAddress());

    输出:

     1 Hibernate: 
    2 select
    3 delivery0_.ID as ID8_,
    4 delivery0_.phone as phone8_,
    5 delivery0_.address as address8_,
    6 delivery0_.POSTCODE as POSTCODE8_,
    7 delivery0_.PARCEL_NUMBER as PARCEL1_9_,
    8 delivery0_.EXPRESS_COMPANY as EXPRESS1_10_,
    9 delivery0_.EXPRESS_NUMBER as EXPRESS2_10_,
    10 delivery0_.clazz_ as clazz_
    11 from
    12 ( select
    13 ID,
    14 phone,
    15 address,
    16 null as EXPRESS_NUMBER,
    17 POSTCODE,
    18 PARCEL_NUMBER,
    19 null as EXPRESS_COMPANY,
    20 1 as clazz_
    21 from
    22 POST_DELIVERY
    23 union
    24 select
    25 ID,
    26 phone,
    27 address,
    28 EXPRESS_NUMBER,
    29 POSTCODE,
    30 null as PARCEL_NUMBER,
    31 EXPRESS_COMPANY,
    32 2 as clazz_
    33 from
    34 EXPRESS_DELIVERY
    35 ) delivery0_
    36 北京西街15号
    37 苏州通信大楼2F

    可见Hibernate把两个子类对应的表的字段合并起来,执行效率低。建议用于父类将来不会修改且不需要多态查询的情况。

    (3)父类子类各有一表,用外键关联,子类表的主键为外键引用父类表的主键

     1 /*mysql*/
    2 create table delivery
    3 (
    4 id int primary key auto_increment,
    5 phone varchar(20),
    6 address varchar(200) not null,
    7 postcode varchar(20)
    8 );
    9 create table post_delivery
    10 (
    11 id int primary key,
    12 parcel_number varchar(20),
    13 foreign key(id) references delivery(id)
    14 );
    15
    16 create table express_delivery
    17 (
    18 id int primary key,
    19 express_company varchar(20),
    20 express_number varchar(20),
    21 foreign key(id) references delivery(id)
    22 );

    例子1:单独子类操作

    1         PostDelivery pDelivery=new PostDelivery();
    2 pDelivery.setPhone("13526356485");
    3 pDelivery.setAddress("北京西街15号");
    4 pDelivery.setPostcode("100080");
    5 pDelivery.setParcelNumber("8578");
    6 session.save(pDelivery);

    输出:

     1 Hibernate: 
    2 insert
    3 into
    4 DELIVERY
    5 (phone, address, POSTCODE)
    6 values
    7 (?, ?, ?)
    8 Hibernate:
    9 insert
    10 into
    11 POST_DELIVERY
    12 (PARCEL_NUMBER, id)
    13 values
    14 (?, ?)

    例子2:多态查询

     1 Hibernate: 
    2 select
    3 delivery0_.ID as ID8_,
    4 delivery0_.phone as phone8_,
    5 delivery0_.address as address8_,
    6 delivery0_.POSTCODE as POSTCODE8_,
    7 delivery0_1_.PARCEL_NUMBER as PARCEL2_9_,
    8 delivery0_2_.EXPRESS_COMPANY as EXPRESS2_10_,
    9 delivery0_2_.EXPRESS_NUMBER as EXPRESS3_10_,
    10 case
    11 when delivery0_1_.id is not null then 1
    12 when delivery0_2_.id is not null then 2
    13 when delivery0_.ID is not null then 0
    14 end as clazz_
    15 from
    16 DELIVERY delivery0_
    17 left outer join
    18 POST_DELIVERY delivery0_1_
    19 on delivery0_.ID=delivery0_1_.id
    20 left outer join
    21 EXPRESS_DELIVERY delivery0_2_
    22 on delivery0_.ID=delivery0_2_.id
    23 北京西街15号
    24 苏州通信大楼2F

    符合数据模型的常规设计规则,类与表的映射匹配更合理。缺点是复杂的类继承下新增数据需要同时操作多个表,查询时通过多个表连接。适用于需要多态查询,同时子类相对来说有较多的新增属性。










  • 相关阅读:
    20Spring_JdbcTemplatem模板工具类
    19Spring_AOP编程(AspectJ)_使用@Pointcut注解来定义切点
    18Spring_AOP编程(AspectJ)_AspectJ的各种通知总结
    17Spring_AOP编程(AspectJ)_AspectJ的注解编程
    14Spring_AOP编程(AspectJ)_环绕通知
    android ViewPager滑动事件讲解
    为listview的item中的元素设置onclick事件
    Android EditText光标颜色 与inputType
    【Android】Android内存溢出问题---用自行开辟的空间进行对内存管理
    【Android】eclipse打不开的解决办法和“Jar mismatch! Fix your dependencies”的解决
  • 原文地址:https://www.cnblogs.com/tazi/p/2301695.html
Copyright © 2020-2023  润新知