Hibernate的3种继承形式
1.     表和子类之间的对立一对一关系 Table per concrete class
源码下载 http://download.csdn.net/source/226662
2.     每个子类对应一张子表,并与主类共享主表 Table per subclass
源码下载 http://download.csdn.net/source/226728
3.     表与类的一对多关系 Table per class hierarchy
源码下载 http://download.csdn.net/source/226783
按照《深入潜出Hibernate》中介绍的,我们开始学习。
 
场景: 就一般的商品而言,在具备某些共性(如: 名称,厂商),也有不同的属性,如书有页数,dvd有dvd的编码格式.
 
<一> table per concerte class
(a) 使用xml
Titem 有两个子类: Tbook , TDvd, 那么,所谓“表与子类之间的一对一的关系”,也就是每个子类对应一张数据库表。对应Tbook , TDvd
数据库的表我们设计如下
    
        
            | 表 T_bool | 
        
            | id | Int | PK | 
        
            | Name | Varchar(50) |   | 
        
            | Manufacturer | Varchar(50) |   | 
        
            | Pagecount | int |   | 
    
 
    
        
            | 表 T_dvd | 
        
            | id | Int | PK | 
        
            | Name | Varchar(50) |   | 
        
            | Manufacturer | Varchar(50) |   | 
        
            | Codetype | Varchar(30) |   | 
    
/**
* 虚拟的表
* TItem 已经知道的继承类为 AbstractTBook AbstractTDvd
*/
public abstract class TItem implements Serializable {
    private Integer id; 
    private String name;
    private String manufacturer;
    public Integer getId() {
       return id;
       }
    public void setId(Integer id) {
       this.id = id;
       }
    public String getManufacturer() {
       return manufacturer;
       }
    public void setManufacturer(String manufacturer) {
       this.manufacturer = manufacturer;
       }
    public String getName() {
       return name;
       }
    public void setName(String name) {
       this.name = name;
       }
}
public abstract class AbstractTDvd extends TItem {
    private String codetype;
    public AbstractTDvd() {     }
    public String getCodetype() {
       return this.codetype;
       }
    public void setCodetype(String codetype) {
       this.codetype = codetype;
       }
}
public abstract class AbstractTBook extends TItem {
    private Integer pagecount;
    public AbstractTBook() {}
    public Integer getPagecount() {
       return this.pagecount;
       }
    public void setPagecount(Integer pagecount) {
       this.pagecount = pagecount;
       }
}
public class TDvd extends AbstractTDvd     {
    public TDvd() {}
}
public class TBook extends AbstractTDvd     {
    public TBook() {}
}
 
Tbook.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping>
       <class name="com.persist.tablePerConcreteClass.TBook" table="t_book" >
           <id name="id" type="java.lang.Integer">
               <column name="id" />
               <generator class="sequence">
               <param name="sequence">t_table_id_seq</param>
               </generator>
           </id>
           <property name="name" type="java.lang.String">
               <column name="name" length="50" />
           </property>
           <property name="manufacturer" type="java.lang.String">
               <column name="manufacturer" length="50" />
           </property>
           <property name="pagecount" type="java.lang.Integer">
               <column name="pagecount" />
           </property>
       </class>
</hibernate-mapping>
 
Tdvd.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping>
       <class name="com.persist.tablePerConcreteClass.TDvd" table="t_dvd" >
           <id name="id" type="java.lang.Integer">
               <column name="id" />
               <generator class="sequence">
               <param name="sequence">t_table_id_seq</param>
               </generator>
           </id>
           <property name="name" type="java.lang.String">
               <column name="name" length="50" />
           </property>
           <property name="manufacturer" type="java.lang.String">
               <column name="manufacturer" length="50" />
           </property>
           <property name="codetype" type="java.lang.String">
               <column name="codetype" length="50" />
           </property>
       </class>
</hibernate-mapping>
 
Hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<hibernate-configuration>
       <session-factory>
          <property name="dialect">
              org.hibernate.dialect.PostgreSQLDialect
          </property>
          <property name="connection.url">
              jdbc:postgresql://localhost:5432/postgres
          </property>
          <property name="connection.username">pgsql</property>
          <property name="connection.password">pgsql</property>
          <property name="connection.driver_class">
              org.postgresql.Driver
          </property>
          <property name="myeclipse.connection.profile">pgsql</property>
          <property name="show_sql">true</property>
          <mapping resource="com/persist/tablePerConcreteClass/TBook.hbm.xml" />
          <mapping resource="com/persist/tablePerConcreteClass/TDvd.hbm.xml" />
       </session-factory>
</hibernate-configuration>
测试用例
public class TBookDAO extends BaseHibernateDAO {
    public static void main(String args[]) {
       new TBookDAO().test();
       }
   
    public void test() {
          Session session = this.getSession();
          List list = session.createQuery(" from com.persist.tablePerConcreteClass.TItem").list();
          Iterator it = list.iterator();
       while (it.hasNext()) {
              TItem item = (TItem) it.next();
              System.out.println(item.getName());
          }
       }
}
 
(b) 使用hibernate注解
步骤1, 修改HibernateSessionFactory 中的Configuration为
AnnotationConfiguration configuration = new AnnotationConfiguration();
步骤2,修改hibernate.cfg.xml中的
<mapping resource="com/persist/tablePerConcreteClass/TBook.hbm.xml" />
<mapping resource="com/persist/tablePerConcreteClass/TDvd.hbm.xml" />
为
<mapping class="com.persist.tablePerConcreteClass.TBook"/>
<mapping class="com.persist.tablePerConcreteClass.TDvd"/>
步骤3,在Titem, AbstractTBook, AbstractTBook类上加注解
@MappedSuperclass
既Titem
@MappedSuperclass
public abstract class TItem implements Serializable {
    @Id
    @Column(name = "id")
    @SequenceGenerator(name = "t_table_id_seq", sequenceName = "t_table_id_seq")
    private Integer id;
    @Column(name = "name")
    private String name;
    @Column(name = "manufacturer")
    private String manufacturer;
    public Integer getId() {
       return id;
    }
    public void setId(Integer id) {
       this.id = id;
    }
    public String getManufacturer() {
       return manufacturer;
    }
    public void setManufacturer(String manufacturer) {
       this.manufacturer = manufacturer;
    }
    public String getName() {
       return name;
    }
    public void setName(String name) {
       this.name = name;
    }
}
AbstractTDvd
@MappedSuperclass
public class AbstractTDvd extends TItem {
    @Column(name = "codetype")
    private String codetype;
    public AbstractTDvd() { }
    public String getCodetype() {
       return this.codetype;
    }
    public void setCodetype(String codetype) {
       this.codetype = codetype;
    }
}
AbstractTBook
@MappedSuperclass
public class AbstractTBook extends TItem {
    @Column(name = "pagecount")
    private Integer pagecount;
    public AbstractTBook() {}
    public Integer getPagecount() {
       return this.pagecount;
    }   public void setPagecount(Integer pagecount) {
       this.pagecount = pagecount;
    }
}
步骤4,在Tbook,TDvd上加注解
@Entity
@Table(name = "t_book")
和
@Entity
@Table(name = "t_dvd")
调用的时候一样
  
<二> Table per subclass
将父类Titem单独映射到一张主表,而为Tbook, TDvd分别建立一张子表,子表和父表用外键来关联
数据库的表我们设计如下
    
        
            | 表 T_item | 
        
            | id | Int  | PK | 
        
            | Name | Varchar(50) |   | 
        
            | Manufacturer | Varchar(50) |   | 
        
            | CREATE TABLE t_item (  id int4 NOT NULL DEFAULT nextval('t_table_id_seq'::regclass),  name varchar(50),  manufacturer varchar(50),  CONSTRAINT t_item_pkey PRIMARY KEY (id) ) | 
    
 
 
    
        
            | 表 T_bool | 
        
            | id | Int  | PK | 
        
            | Pagecount | int |   | 
        
            | CREATE TABLE t_book (  id int4 NOT NULL,  pagecount int4,  CONSTRAINT t_book_pkey PRIMARY KEY (id),  CONSTRAINT t_book_id_fkey FOREIGN KEY (id)       REFERENCES t_item (id) MATCH SIMPLE       ON UPDATE NO ACTION ON DELETE NO ACTION ) | 
    
 
    
        
            | 表 T_dvd | 
        
            | id | Int  | PK | 
        
            | Codetype | Varchar(30) |   | 
        
            | CREATE TABLE t_dvd (  id int4 NOT NULL,  codetype varchar(30),  CONSTRAINT t_dvd_pkey PRIMARY KEY (id),  CONSTRAINT t_dvd_id_fkey FOREIGN KEY (id)       REFERENCES t_item (id) MATCH SIMPLE       ON UPDATE NO ACTION ON DELETE NO ACTION ) | 
    
 
只有1个xml,TItem.hbm.xml
<hibernate-mapping>
     <class name="com.persist.tablePerConcreteClass.TItem" table="t_item">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="sequence">
              <param name="sequence">t_table_id_seq</param>
             </generator>
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="50" />
         </property>
         <property name="manufacturer" type="java.lang.String">
             <column name="manufacturer" length="50" />
         </property>
        
         <joined-subclass name="com.persist.tablePerConcreteClass.TBook" table="t_book">
          <key column="id"></key>
          <property name="pagecount" column="pagecount">
          </property>
         </joined-subclass>
         <joined-subclass name="com.persist.tablePerConcreteClass.TDvd" table="t_dvd">
          <key column="id"></key>
          <property name="codetype" column="codetype">
          </property>
         </joined-subclass>
     </class>
</hibernate-mapping>
使用注解
1.TItem不为抽象类,TItem的类注解为
@Entity
@Table(name = "t_item")
@Inheritance(strategy=InheritanceType.JOINED)
2.AbstractTBook和AbstractTDvd的类注解为
@PrimaryKeyJoinColumn(name="id")
3.TBook和TDvd的注解为
@Entity
@Table(name = "t_book")
和
@Entity
@Table(name = "t_dvd")
<三> Table per class hierarchy
CREATE TABLE t_item
(
 id int4 NOT NULL DEFAULT nextval('t_table_id_seq'::regclass),
 name varchar(50),
 manufacturer varchar(50),
 category varchar(30),
 codetype varchar(30),
 pagecount int4,
 CONSTRAINT t_item_pkey PRIMARY KEY (id)
)
只有一个xml,TItem.hbm.xml
<hibernate-mapping>
    <class name="com.persist.tablePerConcreteClass.TItem" table="t_item">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="sequence">
             <param name="sequence">t_table_id_seq</param>
            </generator>
        </id>
        <discriminator>
            <column name="category" length="10" />
        </discriminator>
        <property name="name" type="java.lang.String">
            <column name="name" length="50" />
        </property>
        <property name="manufacturer" type="java.lang.String">
            <column name="manufacturer" length="50" />
        </property>        
        <subclass name="com.persist.tablePerConcreteClass.TBook" discriminator-value="1">
         <property name="pagecount" column="pagecount">
         </property>
        </subclass>
        <subclass name="com.persist.tablePerConcreteClass.TDvd" discriminator-value="2" >
         <property name="codetype" column="codetype">
         </property>
        </subclass>
    </class>
</hibernate-mapping>
注解的修改为
1.TItem的注解修改为
@Entity
@Table(name = "t_item")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="category", discriminatorType=DiscriminatorType.STRING, length=30)
2.AbstractTBook, AbstractTDvd的注解修改为
@Inheritance
3.TBook,TDvd的注解修改为
@Entity
@DiscriminatorValue(value="2")
</script>