版权声明:本文为博主原创文章,如需转载请标注转载地址。
博客地址: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父类型的数据