有三种方式:
以论坛为例:
父类:Article.java
主帖:Topic extend Article
回复:Reply extend Article
方案一:
由于大部分属性相同,可以只创建一个表,存放所有数据,没有的就填写null,用类型来分辨 具体类型。
方案二:
创建三个表,每个表都只有自己的属性。
方案三:
创建两个子表,两个子表都拥有父类表的属性:
看代码:
public class Article {
private Integer id;
private String title;
private String content;
private Date postTime;
...
}
public class Reply extends Article {
private int floor; // 楼层
...
}
public class Topic extends Article {
private int type; // 精华、置顶...
...
}
下面是三种映射方式
方案一(一张表):
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.j_hbm_extends">
<!--
discriminator-value属性:
用于鉴别是哪个类的一个值,表示这个值就是这个类。
如果不写,默认为类的全限定名。
-->
<class name="Article" table="article" discriminator-value="Aticle">
<id name="id">
<generator class="native"/>
</id>
<!-- 用于鉴别是什么类型的一个列 -->
<discriminator type="string" column="class_"></discriminator>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<subclass name="Topic" discriminator-value="Topic">
<property name="type"></property>
</subclass>
<!-- 子类:Reply -->
<subclass name="Reply" discriminator-value="Reply">
<property name="floor"></property>
</subclass>
</class>
</hibernate-mapping>
方案二 (三张表)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.j_hbm_extends2">
<!-- 采用每个类一张表的方式,抽象类也对应表。 -->
<class name="Article" table="article2">
<id name="id">
<generator class="native"/>
</id>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<joined-subclass name="Topic" table="topic2">
<key column="id"></key>
<property name="type"></property>
</joined-subclass>
<!-- 子类:Reply -->
<joined-subclass name="Reply" table="reply2">
<key column="id"></key>
<property name="floor"></property>
</joined-subclass>
</class>
</hibernate-mapping>
方案三(两种表)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.j_hbm_extends3">
<!-- 采用每个具体类一张表的方式,抽象类不对应表。
abstract默认为false,设为true表示本类不对应表(类可以不是abstract的),这时就会忽略table属性。
-->
<class name="Article" abstract="false" table="article3">
<id name="id">
<!--
当使用每个具体类一张表的方式时,主键生成策略不能是identity。
因为在整个继承结构中,主键值是不能重复的。
-->
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<union-subclass name="Topic" table="topic3">
<property name="type"></property>
</union-subclass>
<!-- 子类:Reply -->
<union-subclass name="Reply" table="reply3">
<property name="floor"></property>
</union-subclass>
</class>
</hibernate-mapping>
测试代码:
package cn.itcast.j_hbm_extends3;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Article.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 新建对象
Article article = new Article();
article.setTitle("这是一个Article");
Topic topic = new Topic();
topic.setTitle("这是一个Topic");
Reply reply = new Reply();
reply.setTitle("这是一个Reply");
// 保存
session.save(article);
session.save(topic);
session.save(reply);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 获取
Article article = (Article) session.get(Article.class, 1);
Topic topic = (Topic) session.get(Topic.class, 2);
Reply reply = (Reply) session.get(Reply.class, 3);
System.out.println(article);
System.out.println(topic);
System.out.println(reply);
System.out.println();
Article article1 = (Article) session.get(Article.class, 2);
Article article2 = (Article) session.get(Article.class, 3);
System.out.println(article1);
System.out.println(article2);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}