Class Hierachy的映射策略之T/CCIP

Hibernate 作为ORM,面对的一个问题是:一个方面是关系型的数据库,另一面是Java Object。Java作为一种面向对象的语言支持继承关系。Hibernate本身提供了4种策略将继承关系映射到关系型的数据库中。他们分别是:

 

  1. Table Per Concrete Class with Implicit Polymorphism : 每个Concrete Class 对应一张Table。利用Hibernate内部的机制来实现多态型的查询。对于SuperClass Query是分成对Concrete Class的独立Query组合起来的。
  2. Table Per Concrete Class with Union : 每个Concrete Class 对应一张Table。对于SuperClass Query是通过Union的方式来实现的。
  3. Table Per Class Hierarchy : 将整个Class Hierachy的关系Mapping到一张Table中,通过discriminator来区分具体的Concrete Class。
  4. Table Per SubClass:对于Class Hierachy图中的每个类都对应有一张Table。

这些策略各有特点,应用场合不同。在具体实现的时候,应该仔细选择。

 

一、例子的背景:

 

 假如我们有如下的类的关系,需要将他们mapping到数据库中

 

  每个类的代码如下:

package org.example.hibernate.domain;

//BillDetail SuperClass
public class BillingDetail {
	
	private Long id;
	
	private String owner;
	
	//省略相应的get/set accessor
}

 

package org.example.hibernate.domain;

//Concrete Class BankAccount
public class BankAccount extends BillingDetail{
	
	private String account; 
	
	private String bankName; 
	
	private String swift;
	
	//省略相应的get/set accessor
}

 

package org.example.hibernate.domain;

//Concrete Class CreditCard
public class CreditCard extends BillingDetail {
	
	private String number; 
	
	private String expMonth;
	
	private String expYear;	

	//省略相应的get/set  accessor
}

 

二、使用T/CCIP(Table Per Concrete Class with Implicit Polymorphism)策略来映射

1. 只对Concrete Class建立Table,SuperClass中的property,直接mapping到Concrete Class相应Table的column

2. 对于Concrete Class的mapping,就如同没有SuperClass的普通Class一样mapping。

 

   Mapping File如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <!-- CreditCard Class Mapping Section-->
    <class name="org.example.hibernate.domain.CreditCard" 
           table="CREDITCARD" polymorphism="implicit">
        
        <id name="id" column="IDNUM" type="long">
            <generator class="native"/>
        </id>
        
        <property name="owner" type="string" column="OWNER" length="30"/>
	    
        <property name="number" type="string" column="NUMBER_CODE" length="20"/>
        
        <property name="expMonth" type="string" column="EXP_MONTH" length="2"/>
	    
        <property name="expYear" type="string" column="EXP_YEAR" length="4"/>

    </class>
     
    <!-- BankAccount Class Mapping Section-->
    <class name="org.example.hibernate.domain.BankAccount" 
           table="BANK_ACCOUNT" polymorphism="implicit">

        <id name="id" column="IDNUM" type="long">
            <generator class="native"/>
        </id>
        
        <property name="owner" type="string" column="OWNER" length="30"/>

        <property name="account" type="string" column="ACCOUNT" length="20"/>

        <property name="bankName" type="string" column="BANK_NAME" length="255"/>

        <property name="swift" type="string" column="SWIFT" length="3"/>

    </class>        

</hibernate-mapping>

 

如Mapping File中看到的,CreditCard和BankAccount的Id都是采用Hibernate的native策略。当Session对CreditCard和BankAccount的instance做save的时候,insert到相应table中的idnum栏位的value可能是一样的。因为他们的Hibernate Id 产生策略独立的,彼此没有任何的关系。 

//Transaction Commit以后,cc11的Id Value是1
CreditCard cc11 = new CreditCard();
cc11.setOwner("jessecia");
cc11.setNumber("123123123123123");		
session.save(cc11);

//Transaction Commit以后,ba11的Id Value是1
BankAccount ba11 = new BankAccount();
ba11.setOwner("jessecia");
ba11.setBankName("GBDFB"); 	
session.save(ba11);

 

    而对于BillingDetail的polymorphic query,则分成2个独立的对CreditCard和BankAccount表的查询SQL来获得。Java代码如下:

Criteria criteria = session.createCriteria(BillingDetail.class);
List<BillingDetail> list = criteria.list();

   

   产生的SQL如下: 

select this_.IDNUM as IDNUM0_0_
     , this_.NUMBER_CODE as NUMBER2_0_0_
     , this_.EXP_MONTH as EXP3_0_0_
     , this_.EXP_YEAR as EXP4_0_0_
     , this_.OWNER as OWNER0_0_ 
from CREDITCARD this_

select this_.IDNUM as IDNUM1_0_
     , this_.ACCOUNT as ACCOUNT1_0_
     , this_.BANK_NAME as BANK3_1_0_
     , this_.SWIFT as SWIFT1_0_
     , this_.OWNER as OWNER1_0_ 
from BANK_ACCOUNT1 this_

 

 T/CCIP方式的结论:

1.  应用场合:不适合于Polymorphic Association的应用场合。也就是说SupperClass和其他的Persistent Class发生关系。

2.  扩展性:当SuperClass增加新的Property的时候,每个Concrete Class相应的Table都需要新增Column

 

 下一篇:Class Hierachy的映射策略之T/CCU

 

你可能感兴趣的:(sql,Hibernate,.net,orm)