版權聲明:本文為博主原創文章,如需轉載請標注轉載地址。
博客地址:http://www.cnblogs.com/caoyc/p/5603724.html
對於繼承關系類的映射。比如在論壇中文章(Ariticla)有主題類型(Topic),有回復類型(Reply)。其中Topic都id、title、context、postDate、type(類型:如普通、精華、置頂......),而Replay有id,title,context,postDate,floor(樓層)。針對這樣的情況,Topic和Replay都有共同的屬性,那么就可以提取出一個抽象類Ariticla,並給Aritcla添加共同屬性id,title,context,postDate。然后讓Topic和Reply繼承Aritcla,然后各自在指定各自的屬性。如圖:

繼承類三種設計方式
第一種:subclass
這種類型的特點,可以使用一張表來存儲所有數據。我們需要在數據庫表設計的時候增加一列用於判斷該條記錄的類型
Sql數據表結構

代碼實現:
Article.java
1 package com.myproc.domain; 2 3 import java.util.Date; 4 5 public class Article { 6 private Integer id; 7 private String title; //標題 8 private String context; //內容 9 private Date postDate; //提交日期 10 public Integer getId() { 11 return id; 12 } 13 public void setId(Integer id) { 14 this.id = id; 15 } 16 public String getTitle() { 17 return title; 18 } 19 public void setTitle(String title) { 20 this.title = title; 21 } 22 public String getContext() { 23 return context; 24 } 25 public void setContext(String context) { 26 this.context = context; 27 } 28 public Date getPostDate() { 29 return postDate; 30 } 31 public void setPostDate(Date postDate) { 32 this.postDate = postDate; 33 } 34 }
Topic.java
1 package com.myproc.domain; 2 3 public class Topic extends Article { 4 private int type; //類型:精華、置頂、推薦...... 5 6 public int getType() { 7 return type; 8 } 9 10 public void setType(int type) { 11 this.type = type; 12 } 13 14 }
Reply.java
1 package com.myproc.domain; 2 3 public class Reply extends Article { 4 private int floor; //樓層 5 6 public int getFloor() { 7 return floor; 8 } 9 10 public void setFloor(int floor) { 11 this.floor = floor; 12 } 13 14 }
Article.hbm.xml
1 <?xml version="1.0"?> 2 3 <!DOCTYPE hibernate-mapping PUBLIC 4 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 5 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 6 <hibernate-mapping package="com.myproc.domain"> 7 <!--discriminator-value:鑒別器的值,如果不指定則為類的全限名(含包) --> 8 <class name="Article" table="t_article" discriminator-value="A"> 9 <id name="id" column="Id" type="integer"> 10 <generator class="native"></generator> 11 </id> 12 <!-- 設置鑒別器,column:在數據庫中的列。根據該列的值判斷是什么類型 --> 13 <discriminator column="class_" type="string"></discriminator> 14 <property name="title" type="string"></property> 15 <property name="context" type="text" length="1000"></property> 16 <property name="postDate" type="timestamp"></property> 17 18 <!-- 子類 --> 19 <subclass name="Topic" discriminator-value="T"> 20 <!-- 子類屬性 --> 21 <property name="type" type="int"></property> 22 </subclass> 23 24 <subclass name="Reply" discriminator-value="R"> 25 <property name="floor"></property> 26 </subclass> 27 </class> 28 </hibernate-mapping>
這里主要知識點:
a、subclass:子類的指定
b、discriminator:鑒別器的設置
測試代碼:
1 package com.myproc.test; 2 3 import java.util.Date; 4 5 import org.hibernate.Session; 6 import org.hibernate.SessionFactory; 7 import org.hibernate.Transaction; 8 import org.hibernate.cfg.Configuration; 9 import org.junit.Test; 10 11 import com.myproc.domain.Article; 12 import com.myproc.domain.Reply; 13 import com.myproc.domain.Topic; 14 15 16 public class App { 17 18 private static SessionFactory factory= 19 new Configuration() 20 .configure() 21 .addClass(Article.class) 22 .buildSessionFactory(); 23 24 @Test 25 public void test(){ 26 27 Session session=factory.openSession(); 28 Transaction tran=session.beginTransaction(); 29 30 Article article=new Article(); 31 article.setTitle("article"); 32 article.setContext("article......."); 33 article.setPostDate(new Date()); 34 35 Topic topic=new Topic(); 36 topic.setTitle("topic"); 37 topic.setContext("topic......."); 38 topic.setPostDate(new Date()); 39 topic.setType(2); 40 41 Reply reply=new Reply(); 42 reply.setTitle("reply"); 43 reply.setContext("reply......."); 44 reply.setPostDate(new Date()); 45 reply.setFloor(1); 46 47 session.save(article); 48 session.save(topic); 49 session.save(reply); 50 51 tran.commit(); 52 session.close(); 53 } 54 }
在數據庫中我們可以看到結果:

第二種方式:joined-subclass
這種方式的特點:有三張表,其中父類對應的表存儲公共屬性,其它各自的表存儲各自的信息,並且在該表中用一個外鍵引用父類對應的表的主鍵,如下圖:

代碼實現:在上例中,我們只需要修改Article.hbm.xml文件,內容如下:
1 <?xml version="1.0"?> 2 3 <!DOCTYPE hibernate-mapping PUBLIC 4 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 5 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 6 <hibernate-mapping package="com.myproc.domain"> 7 <class name="Article" table="t_article" > 8 <id name="id" column="Id" type="integer"> 9 <generator class="native"></generator> 10 </id> 11 <property name="title" type="string"></property> 12 <property name="context" type="text" length="1000"></property> 13 <property name="postDate" type="timestamp"></property> 14 15 <joined-subclass name="Topic" table="t_topic"> 16 <!-- 指定子類的外鍵 --> 17 <key column="id"></key> 18 <property name="type"></property> 19 </joined-subclass> 20 21 <joined-subclass name="Reply" table="t_reply"> 22 <key column="id"></key> 23 <property name="floor"></property> 24 </joined-subclass> 25 </class> 26 </hibernate-mapping>
當執行測試代碼后:
在數據庫會自動生成3張表

t_article表中數據:

t_topic

t_reply

第三種方式:union-subclass
特點:使用兩張表存儲數據,如下圖:

同樣只需要要修改Article.hbm.xml文件
1 <?xml version="1.0"?> 2 3 <!DOCTYPE hibernate-mapping PUBLIC 4 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 5 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 6 <hibernate-mapping package="com.myproc.domain"> 7 <!-- 這里使用abstract=“true”,表示不再數據庫中創建對應的表(這里的類不一定是抽象類) --> 8 <class name="Article" table="t_article" abstract="true"> 9 <id name="id" column="Id" type="integer"> 10 <!-- 這里不能使用identity方式,在hibernate5.2版本也不支持hilo,這里使用MultipleHiLoPerTableGenerator,方式和hilo一樣 --> 11 <generator class="org.hibernate.id.MultipleHiLoPerTableGenerator"> 12 <param name="max_lo">100</param> 13 </generator> 14 </id> 15 <property name="title" type="string"></property> 16 <property name="context" type="text" length="1000"></property> 17 <property name="postDate" type="timestamp"></property> 18 19 <union-subclass name="Topic" table="t_topic"> 20 <property name="type"></property> 21 </union-subclass> 22 23 <union-subclass name="Reply" table="t_reply"></union-subclass> 24 </class> 25 </hibernate-mapping>
在測試代碼中也不要保存Article父類型的數據




