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>