注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

北漂的小羊

Java编程,开发者,程序员,软件开发,编程,代码。新浪微博号:IT国子监

 
 
 

日志

 
 
关于我

在这里是面向程序员的高品质IT技术学习社区,是程序员学习成长的地方。让我们更好地用技术改变世界。请关注新浪微博号: IT国子监(http://weibo.com/itguozijian)

网易考拉推荐

JPA标准、Hibernate中类与类之间关系:继承关系  

2013-01-06 18:00:33|  分类: hibernate |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在Java或.Net类与类之间存在关联、聚集和继承关系。一般来说:
关联关系:采用“一对多或一对一”的映射即可;
聚集关系:采用“集和映射”,即映射Set,Bag,List,Map
继承关系:本文以下详述

Hibernate中继承关系的简介:
java是一种面向对象语言,它可以实现继承关系。然而,继承却是"对象模型-关系模型"不匹配的最显而易见的方面之一。面向对象系统能够轻松的对“is a”和“has a”关系进行建模。而关系模型只能表达两个实体间的"has a"关系。hibernate能够把有关联的表映射为对象,但你需要根据需要来选择不同的映射策略。
Hibernate继承关系映射策略分为三种:一张表对应一整棵类继承树、一个类对应一张表、每一个具体类对应一张表。
之一:一张表对应一整棵类继承树(子类和父类共享同一张表)
假设我们有一个 Person 类及其子类 Employee. 每个类包括如下属性:
* class Person         - firstname         - lastname  * class Employee         - joining_date         - department_name
在“一张表对应一整棵类继承树”这种模式中,继承树上的所有类的数据都存储在一张表上,鉴别器字段(discriminator )是唯一的标识每个类的关键字段。
下面是“一张表对应一整棵类继承树”模式的优点和缺点:
优点

这种模式提供了最好的性能,因为即使在深层继承的情况下,检索一条子类数据,也只需要一次select操作。
缺点:对于任何一个子类的变更,比如增删改某字段,都将导致数据库表的变更。 

PERSON表被用来同时存储 Employee 和 Person 对象. 
Hibernate 继承: XML 映射 
下面的例子展示了如何用XML方式映射  Employee 和 Person 实体类. 
Person.java 

package net.viralpatel.hibernate;   public class Person {       private Long personId;     private String firstname;     private String lastname;       // Constructors and Getter/Setter methods, }

Employee.java
package net.viralpatel.hibernate;   import java.util.Date;   public class Employee extends Person {       private Date joiningDate;     private String departmentName;       // Constructors and Getter/Setter methods, }

Person.hbm.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"         "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">   <hibernate-mapping package="net.viralpatel.hibernate">       <class name="Person" table="PERSON" discriminator-value="P">         <id name="personId" column="PERSON_ID">             <generator class="native" />         </id>           <discriminator column="DISCRIMINATOR" type="string" />           <property name="firstname" />         <property name="lastname" column="lastname" />           <subclass name="Employee" extends="Person" discriminator-value="E">                 <property name="departmentName" column="department_name" />                 <property name="joiningDate" type="date" column="joining_date" />         </subclass>     </class> </hibernate-mapping>
注意这里只定义了一个 hibernate 映射文件 Person.hbm.xml.
Person 和 Employee 类都定义在这同一个文件中.
<discriminator> 标签用来指定鉴别器列,包括列名和类型.

<subclass> 标签用于映射子类 Employee. 注意我们没有用常规的 <class>标签来映射 Employee ,因为它位于继承关系树下端。

Person 类的鉴别器的值被指定为 “P” ,相应的 Employee 是“E”,这样, 当Hibernate将要持久化person 或 employee时,相应的“P”或“E”将被置入鉴别器字段。


Hibernate 继承: 注解映射


  在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class)、Joined策略(table per subclass)和Table_PER_Class策略。

1.单表继承策略

   

    单表继承策略,父类实体和子类实体共用一张数据库表,在表中通过一列辨别字段来区别不同类别的实体。具体做法如下:

a.在父类实体的@Entity注解下添加如下的注解:

@Inheritance(Strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”辨别字段列名”)
@DiscriminatorValue(父类实体辨别字段列值)

 

b.在子类实体的@Entity注解下添加如下的注解:

@DiscriminatorValue(子类实体辨别字段列值) 


2.Joined策略

 

    父类实体和子类实体分别对应数据库中不同的表,子类实体的表中只存在其扩展的特殊属性,父类的公共属性保存在父类实体映射表中。具体做法

 

@Inheritance(Strategy=InheritanceType.JOINED)


3.Table_PER_Class策略:

 

Table_PER_Class策略,父类实体和子类实体每个类分别对应一张数据库中的表,子类表中保存所有属性,包括从父类实体中继承的属性。具体做法:

只需在父类实体的@Entity注解下添加如下注解:

@Inheritance(Strategy=InheritanceType.TABLE_PER_CLASS)



 下面的例子展示了如何用JPA注解方式来映射 Employee  Person 实体类。

 Person.java 

package net.viralpatel.hibernate;   import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table;   @Entity @Table(name = "PERSON") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(     name="discriminator",     discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue(value="P") public class Person {       @Id     @GeneratedValue     @Column(name = "PERSON_ID")     private Long personId;       @Column(name = "FIRSTNAME")     private String firstname;       @Column(name = "LASTNAME")     private String lastname;       // Constructors and Getter/Setter methods, }

Person 类是继承树的根类,所以我们使用了下面一些注解使其成为根类。

@Inheritance – 定义一个实体类继承树的继承策略,这个注解只能定义在继承树的根类上。

@DiscriminatorColumn – 用于当@Inheritance 的值被定义为 SINGLE_TABLE 或 JOINED 时,指定鉴别器列。 此注解只能用于两种类:一、继承树的根类,二、继承树的某子类,并且该子类定义了自己继承策略。

如果在需要鉴别器列的时候,没有使用@DiscriminatorColumn注解,那么鉴别器列的名称将默认为“DTYPE”,类型将默认为“STRING”。

@DiscriminatorValue – 用于指定给定实体类所对应的鉴别器列的具体值。 DiscriminatorValue 注解只能用在具体的实体类中。如果使用了鉴别器列,但是没有使用 DiscriminatorValue 注解,一个鉴别器值生成器将生效并产生一个鉴别器值来代表这个类。如果鉴别器列的类型是 STRING,  鉴别器列的值默认是该类的名称。如果不采用默认值,那么应该在继承树的每个类中都使用该注解。

Employee.java 

package net.viralpatel.hibernate;   import java.util.Date;   import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table;   @Entity @Table(name="PERSON") @DiscriminatorValue("E") public class Employee extends Person {       @Column(name="joining_date")     private Date joiningDate;       @Column(name="department_name")     private String departmentName;       // Constructors and Getter/Setter methods, }

Employee类是Person类的子类,所以在映射时,使用@DiscriminatorValue注解来定义鉴别器的值,此例中,“E”将被置入鉴别器列。 

 MainClass

  import java.util.Date;   import org.hibernate.Session; import org.hibernate.SessionFactory;   public class Main {       public static void main(String[] args) {           SessionFactory sf = HibernateUtil.getSessionFactory();         Session session = sf.openSession();         session.beginTransaction();           Person person = new Person("Steve", "Balmer");         session.save(person);           Employee employee = new Employee("James", "Gosling", "Marketing", new Date());         session.save(employee);           session.getTransaction().commit();         session.close();       } }

Main class 用来持久化 Person      Employee类的实例。注意两个类都存储在PERSON表中,鉴别器列用于区分两个实体。

 输出结果

Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, discriminator) values (?, ?, 'P') Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, department_name, joining_date, discriminator) values (?, ?, ?, ?, 'E')

JPA标准、Hibernate中类与类之间关系:继承关系 - 天涯草 - 天涯草


  评论这张
 
阅读(1050)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016