06. 继承关系映射

继承关系映射

继承关系映射分为三种:

  • 整个继承结构映射一张表

  • 每个类映射一张表

    有多少个类就映射多少张表,包括子类父类

  • 每个具体子类映射一张表

    只需要每个子类映射一张表,而父类不映射到表

用到的例子

在研究继承关系映射时,我们用到了一个继承关系的例子。

父类:BillingDetails(账单明细)

  • id:Long

  • owner:String(拥有者)

  • code:String(卡号)

  • created:Date(创建时间)

  • setter、getter方法

子类:BankAccount(银行账户)

  • bankName:String(银行名称)

  • bankSwift:String(银行的简称)

子类:CreditCard(信用卡)

  • type:String(信用卡类型)

  • expMonth:String(有效时间,月份)

  • expYear:String(有效时间,年份)

BillingDetails类

package com.li.inheritance.pojo;

import java.io.Serializable;
import java.util.Date;

public class BillingDetails implements Serializable{

    private Long id;
    private String owner;
    private String code;
    private Date created;


    public BillingDetails() {
        super();
    }
    public BillingDetails(Long id, String owner, String code, Date created) {
        super();
        this.id = id;
        this.owner = owner;
        this.code = code;
        this.created = created;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Date getCreated() {
        return created;
    }
    public void setCreated(Date created) {
        this.created = created;
    }
    @Override
    public String toString() {
        return "BillingDetails [id=" + id + ", owner=" + owner + ", code=" + code + ", created=" + created + "]";
    }



}

CreditCard类

package com.li.inheritance.pojo;

import java.io.Serializable;
import java.util.Date;

public class CreditCard extends BillingDetails implements Serializable {
    private String Type;
    private String expMonth;
    private String expYear;

    public CreditCard() {}

    public CreditCard(Long id, String owner, String code, Date created, String type, String expMonth, String expYear) {
        /*调用父类的构造方法*/
        super(id, owner, code, created);
        Type = type;
        this.expMonth = expMonth;
        this.expYear = expYear;
    }

    public String getType() {
        return Type;
    }

    public void setType(String type) {
        Type = type;
    }

    public String getExpMonth() {
        return expMonth;
    }

    public void setExpMonth(String expMonth) {
        this.expMonth = expMonth;
    }

    public String getExpYear() {
        return expYear;
    }

    public void setExpYear(String expYear) {
        this.expYear = expYear;
    }

    @Override
    public String toString() {
        return "CreditCard [Type=" + Type + ", expMonth=" + expMonth + ", expYear=" + expYear + "]";
    }

}

BankAccount类

package com.li.inheritance.pojo;

import java.io.Serializable;
import java.util.Date;

public class BankAccount extends BillingDetails implements Serializable {
    private String bankName;
    private String bankSwift;

    public BankAccount() {}

    public BankAccount(Long id, String owner, String code, Date created, String bankName, String bankSwift) {
        super(id, owner, code, created);
        this.bankName = bankName;
        this.bankSwift = bankSwift;
    }


    public String getBankName() {
        return bankName;
    }

    public void setBankName(String bankName) {
        this.bankName = bankName;
    }

    public String getBankSwift() {
        return bankSwift;
    }

    public void setBankSwift(String bankSwift) {
        this.bankSwift = bankSwift;
    }

    @Override
    public String toString() {
        return "BankAccount [bankName=" + bankName + ", bankSwift=" + bankSwift + "]";
    }


}

整个映射结构映射到一张表

此方式支持多态,根据父类查找一个子类信息能查找到

表结构
CREATE TABLE t_hierarchy(
    id NUMBER(10) PRIMARY KEY,
    owner VARCHAR2(15),
    code VARCHAR2(15),
    created DATE,
    bankname VARCHAR2(20),
    bankswift VARCHAR2(20),
    credit_card_type VARCHAR2(20),
    expired_month VARCHAR2(20),
    expired_year VARCHAR2(20),
    account_type VARCHAR2(20)
);

这张表结构存储了整个继承结构的内容,包含了父类和子类的内容,而最后一列 “account_type” 用以区分记录的来源,记录可以来源于父类(BilliingDetails),也可以是子类BankAccount、子类CreditCard,我们把此列作为一个标识。

映射文件
  • discriminator-value:每个类的唯一标识,区分记录的来源

  • discriminator:name属性标明表中用来区分记录来源的栏位,type指明了类型,如下:如果ACCOUNT_TYPE的值为CC,则说明该记录是通过CreditCard映射过来的

  • subclass:配置子类

  • 主键生成策略只需配置父类即可,主键也在父类中

<class name="BillingDetails" table="t_hierarchy" discriminator-value="BD">
    ...
    <discriminator column="ACCOUNT_TYPE" type="string"/>
    ...
    <subclass name="CreditCard" discriminator-value="CC">...</subclass>
    <subclass name="BankAccount" discriminator-value="BA">...</subclass>
</class>

hierarchy.hbm.xml映射文件,完成之后配置到核心配置文件中

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

<hibernate-mapping>

    <class name="com.li.inheritance.pojo.BillingDetails" table="T_HIERARCHY" discriminator-value="BD">
        <id name="id" column="ID" type="long">
            <generator class="assigned"></generator>
        </id>
        <discriminator column="ACCOUNT_TYPE" type="string"></discriminator>
        <property name="owner" column="OWNER" type="string"></property>
        <property name="code" column="CODE" type="string"></property>
        <property name="created" column="CREATED" type="string"></property>

        <subclass name="com.li.inheritance.pojo.CreditCard" discriminator-value="CC">
            <property name="type" column="CREDIT_CARD_TYPE" type="string"></property>
            <property name="expMonth" column="EXPIRED_MONTH" type="string"></property>
            <property name="expYear" column="EXPIRED_YEAR" type="string"></property>
        </subclass>

        <subclass name="com.li.inheritance.pojo.BankAccount" discriminator-value="BA">
            <property name="bankName" column="BANKNAME" type="string"></property>
            <property name="bankSwift" column="BANKSWIFT" type="string"></property>
        </subclass>
    </class>

</hibernate-mapping>
测试
package com.li.inheritance.pojo;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.li.common.HibernateSessionFactory;

public class HierarchyTest {

    public static void main(String[] args) {
        BillingDetails bd=new BillingDetails();
        bd.setId(123L);
        bd.setCode("111");
        bd.setOwner("Lin");
        bd.setCreated(new Date(System.currentTimeMillis()));

        BankAccount ba=new BankAccount();
        ba.setBankName("ChinaBank");
        ba.setBankSwift("cnb");
        ba.setCreated(new Date(System.currentTimeMillis()));
        ba.setId(456L);
        ba.setCode("222");
        ba.setOwner("White");

        CreditCard cc=new CreditCard();
        cc.setId(789L);
        cc.setCode("333");
        cc.setOwner("Lucy");
        cc.setCreated(new Date(System.currentTimeMillis()));
        cc.setExpMonth("6");
        cc.setExpYear("2018");

        Session session = HibernateSessionFactory.getSession();
        Transaction trans=null;

        try {
            trans=session.beginTransaction();
            session.save(bd);
            session.save(ba);
            session.save(cc);

            BillingDetails account=(BillingDetails) session.get(BankAccount.class, 456L);
            /*多态,下面这种方式能通过父类查找到子类*/
            BillingDetails account=(BillingDetails) session.get(BillingDetails.class, 456L);
            System.out.println(account);

            trans.commit();
        } catch (Exception e) {
            e.printStackTrace();
            trans.rollback();
        }
    }

}

数据库记录

这里写图片描述

改进

实际上我们创建一个父类(BillingDetails)对象并持久化到数据库中没有任何意义,因为子类就包括了父类的所有信息,而父类映射到数据库中没有实际意义,所以我们通常将父类声明为抽象类,那么我们就不能是哟 new 关键字来实例化父类了。

每个类映射一张表

此方式支持多态,根据父类查找一个子类信息能查找到

表结构

表名中间加join是因为我们的操作中有join操作。我们把子表中的主键又作为外键映射到父表中的主键,实现了表与表的关联。

t_join_billingdetails表(父表)

CREATE TABLE t_join_billingdetails(
    id NUMBER(10) PRIMARY KEY,
    owner VARCHAR2(15),
    code VARCHAR2(15),
    created DATE
);

t_join_bankaccount表(子表)

CREATE TABLE t_join_bankaccount(
    billing_id NUMBER(10) PRIMARY KEY,
    bankname VARCHAR2(20),
    bankswift VARCHAR2(20),
    FOREIGN KEY(billing_id) REFERENCES t_join_billingdetails(id)
);

t_join_creditcard表(子表)

CREATE TABLE t_join_creditcard(
    billing_id NUMBER(10) PRIMARY KEY,
    credit_card_type VARCHAR2 (20),
    expired_month VARCHAR2 (20),
    expired_year VARCHAR2 (20),
    FOREIGN KEY(billing_id) REFERENCES t_join_billingdetails(id)
);
映射文件

join.hbm.xml映射文件,完成之后配置到核心配置文件中

其中key标签设置表对应的外键列。

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

<hibernate-mapping package="com.li.inheritance.pojo">
    <class name="BillingDetails" table="T_JOIN_BILLINGDETAILS">
        <id name="id" column="ID" type="long">
            <generator class="assigned"></generator>
        </id>
        <property name="owner" column="OWNER" type="string"></property>
        <property name="code" column="CODE" type="string"></property>
        <property name="created" column="CREATED" type="string"></property>

        <joined-subclass name="CreditCard" table="T_JOIN_CREDITCARD">
            <key column="BILLING_ID"/>
            <property name="type" column="CREDIT_CARD_TYPE" type="string"></property>
            <property name="expMonth" column="EXPIRED_MONTH" type="string"></property>
            <property name="expYear" column="EXPIRED_YEAR" type="string"></property>
        </joined-subclass>
        <joined-subclass name="BankAccount" table="T_JOIN_BANKACCOUNT">
            <key column="BILLING_ID"/>
            <property name="bankName" column="BANKNAME" type="string"></property>
            <property name="bankSwift" column="BANKSWIFT" type="string"></property>
        </joined-subclass>
    </class>
</hibernate-mapping>

每个具体子类映射一张表

此方式不支持多态,根据父类查找一个子类信息不能查找到

表结构

concrete:混泥土,表示具体的意思

t_concrete_bankaccount表

CREATE TABLE t_concrete_bankaccount(
    id NUMBER(10) PRIMARY KEY,
    owner VARCHAR2(15),
    code VARCHAR2(15),
    created DATE,
    bankname VARCHAR2(20),
    bankswift VARCHAR2(20)
);

t_concrete_creditcard表

CREATE TABLE t_concrete_bankaccount(
    id NUMBER(10) PRIMARY KEY,
    owner VARCHAR2(15),
    code VARCHAR2(15),
    created DATE,
    credit_card_type VARCHAR2(20),
    expired_month VARCHAR2(20),
    expired_year VARCHAR2(20)
);
映射文件

concrete.hbm.xml

最外层的class指定父类,但是父类不映射表结构,所有无需配置对应的表,还配置对应的主键生成策略和属性。

对子类我们使用union-subclass来配置,子类独有的属性我们需要配置在子类中

完成映射文件,再把映射文件配置到核心配置文件中hibernate.cfg.xml

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

<hibernate-mapping package="com.li.inheritance.pojo">
    <class name="BillingDetails">
        <id name="id" column="ID" type="long">
            <generator class="assigned"></generator>
        </id>
        <property name="owner" column="OWNER" type="string"></property>
        <property name="code" column="CODE" type="string"></property>
        <property name="created" column="CREATED" type="string"></property>

        <union-subclass name="CreditCard" table="T_CONCRETE_CREDITCARD">
            <property name="type" column="CREDIT_CARD_TYPE" type="string"></property>
            <property name="expMonth" column="EXPIRED_MONTH" type="string"></property>
            <property name="expYear" column="EXPIRED_YEAR" type="string"></property>
        </union-subclass>
        <union-subclass name="BankAccount" table="T_CONCRETE_BANKACCOUNT">
            <property name="bankName" column="BANKNAME" type="string"></property>
            <property name="bankSwift" column="BANKSWIFT" type="string"></property>
        </union-subclass>
    </class>
</hibernate-mapping>

继承关系小结

分类多态更新维护出具报表
整个继承结构映射一张表支持
每个类映射一张表支持
每个具体子类映射一张表不支持

多态:即一张表中存储多种类型的记录

不支持多态的用的不多,其中第二种用的更多一点

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值