Hibernate的3種繼承形式
1. 表和子類之間的對(duì)立一對(duì)一關(guān)系 Table per concrete class
源碼下載 http://download.csdn.net/source/226662
2. 每個(gè)子類對(duì)應(yīng)一張子表,并與主類共享主表 Table per subclass
源碼下載 http://download.csdn.net/source/226728
3. 表與類的一對(duì)多關(guān)系 Table per class hierarchy
源碼下載 http://download.csdn.net/source/226783
按照《深入潛出Hibernate》中介紹的,我們開始學(xué)習(xí)。
場(chǎng)景: 就一般的商品而言,在具備某些共性(如: 名稱,廠商),也有不同的屬性,如書有頁(yè)數(shù),dvd有dvd的編碼格式.
<一> table per concerte class
(a) 使用xml
Titem 有兩個(gè)子類: Tbook , TDvd, 那么,所謂“表與子類之間的一對(duì)一的關(guān)系”,也就是每個(gè)子類對(duì)應(yīng)一張數(shù)據(jù)庫(kù)表。對(duì)應(yīng)Tbook , TDvd
數(shù)據(jù)庫(kù)的表我們?cè)O(shè)計(jì)如下
表 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 已經(jīng)知道的繼承類為 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>
測(cè)試用例
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")
調(diào)用的時(shí)候一樣
<二> Table per subclass
將父類Titem單獨(dú)映射到一張主表,而為Tbook, TDvd分別建立一張子表,子表和父表用外鍵來關(guān)聯(lián)
數(shù)據(jù)庫(kù)的表我們?cè)O(shè)計(jì)如下
表 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個(gè)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)
)
只有一個(gè)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>