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>