首页 > 其他分享 >hibernate——继承关系以及三个subclass标签的区别

hibernate——继承关系以及三个subclass标签的区别

时间:2023-08-27 11:07:39浏览次数:36  
标签:hibernate 标签 subclass 主键 子类 父类 id


Java类中有继承关系,相应的在hibernate中,也有继承关系,子类反应到数据库中,就有多种实现形式了,子类和父类可以映射到同一张表中,子类也可以单独映射成一张表,但是用不同的标签实现,子类表和父类表的关系也不同。在映射文件中,有三个标签可以实现继承关系,分别是:subclass、joined-subclass、union-subclass,先陈述一下这三个标签的区别:

subclass标签就是为子类嵌入父类的表中而设计的,而且要指定鉴别器,即用subclass一定要有判断类型的一个列,鉴别器指定记录属于哪个类型。但是subclass也提供了为子类设置单独的表的功能,即join标签。但是不管是内嵌表还是外部表,都得指定鉴别器。

joined-subclass标签,提供的功能是只能为子类设定外部表,而且没有鉴别器,即子类一张表,父类一张表,子类以父类的主键为外键。父类对应的表中,没有判断类型的列。

注意:这两个标签不能混用,若是只想要内嵌表,或者是既想要有内嵌表,又想要外部表,又或者是只想要外部表,那么只能使用subclass标签,需要注意的是,不论哪种方式,都要指定鉴别器,即父类对应的表中,一定有一个判断类型的列;而若是只想要外部表,又不想在父类对应的表中,要那个判断类型的列,那么只能使用join-subclass

union-subclass是将父类中的属性,添加到子类对应的表中去了。包括父类中的外键。union-class和前两个的区别就在于外键的不同,前两个标签,如果子类有单独对应的表的话,这个表的外键是其父类中的主键,而使用union-class,子类对应的表中的外键则和父类的外键是一样的,因为子类把父类继承的属性,也加到了自己的表当中。这样子类和父类的地位就相当了。不过这不是一种好的理解方式。如果是这样的话,那么就可以把父类设为抽象的类,并且在映射文件中,把父类设置为abstract="true",那么就不会再数据库中生成父类对应的表了,父类就只起到一个抽象的作用了。

下面列举员工和部门的例子说明,假设员工类还有两个子类:一个是技术人员,一个是销售人员:

public class Employee {
	private int id;
	private String name;
	private Department depart;

        ……//set/get方法
}
public class Skiller extends Employee {
	private String skill;

        ……//set/get方法
}
public class Saler extends Employee {
	private String sale;
	private int age;

        ……//set/get方法
}
public class Department {
	private int id;
	private String name;
	private Set<Employee> emps;

        ……//set/get方法
}


部门类的映射文件:

<class name="Department">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		
		<set name="emps" inverse="true">
			<key column="depart_id"/>
			<one-to-many class="Employee"/>
		</set>
</class>



(1)下面关键是员工类的映射文件,我们先来看使用subclass标签的情况:

<class name="Employee" discriminator-value="0">
		<id name="id">
			<generator class="native"/>
		</id>
		<discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
		<property name="name"/>
		<many-to-one name="depart" column="depart_id"/>
		
		<subclass name="Skiller" discriminator-value="1">
			<property name="skill"/>
		</subclass>
		<subclass name="Saler" discriminator-value="2">
			<property name="sale"/>
		</subclass>
</class>

这种情况就是所谓的将整个继承树映射到同一个表当中,即子类的信息,全部映射到了父类对应的表中。注意,一定要指定鉴别器,它的作用是在父类的映射表中,添加了一个type的列,用来鉴别员工是属于哪个子类,并且在每个类的标签中要指定鉴别器值,如上例中用0表示是普通的员工,用1表示技术人员,用2表示销售人员。我们可以看看创建表的ddl语句:

CREATE TABLE `employee` (
  `id` int(11) NOT NULL,
  `type` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `depart_id` int(11) DEFAULT NULL,
  `skill` varchar(255) DEFAULT NULL,
  `sale` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK4AFD4ACE972E0614` (`depart_id`),
  CONSTRAINT `FK4AFD4ACE972E0614` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

用这种方式有缺点有优点,缺点是在表中,会有很多的空值,假如又有了新的子类,那么就要修改表的结构,并且相应的空值会更多;优点是所有信息整合到一张表中,查询的效率高。

下面再来看subclass标签的第二种用法:

<class name="Employee" discriminator-value="0"><!--  discriminator-value="0" -->
		<id name="id">
			<generator class="native"/>
		</id>
		<discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
		<property name="name"/>
		<many-to-one name="depart" column="depart_id"/>
		
		<subclass name="Skiller" discriminator-value="1">
			<property name="skill"/>
		</subclass>
		
		<subclass name="Saler" discriminator-value="2">
			<join table="saler">
				<key column="emp_id"/>
				<property name="sale"/>
			</join>
		</subclass>
</class>

改变的地方,主要是Saler类的标签,在subclass标签中用join标签,这样就为Saler子类单独映射了一个saler表,其主键为父类对应的表的主键。而Skiller类还是和父类映射到了一张表中。来看看Saler创建表的ddl语句:

CREATE TABLE `saler` (
  `emp_id` int(11) NOT NULL,
  `sale` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`emp_id`),
  KEY `FK682490B3F739201` (`emp_id`),
  CONSTRAINT `FK682490B3F739201` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk


需要注意的一个地方是这个表的外键,外键和主键是一样的,都是父类表的主键。




(2)joined-subclass的使用

<class name="Employee"><!--  discriminator-value="0" -->
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<many-to-one name="depart" column="depart_id"/>

		<joined-subclass name="Skiller" table="skiller">
			<key column="emp_id"/>
			<property name="skill"/>
		</joined-subclass>
		<joined-subclass name="Saler" table="saler">
			<key column="emp_id"/>
			<property name="sale"/>
		</joined-subclass>
</class>

用joined-subclass只能创建为子类单独创建表,子类对应的表的主键和外键都是其父类的主键。注意,joined-subclass不能和subclass混合使用。


(3)union-subclass的使用

<class name="Employee">
		<id name="id">
			<generator class="hilo"/>
		</id>
		<property name="name"/>
		<many-to-one name="depart" column="depart_id"/>

		<union-subclass name="Skiller" table="skiller">
			<property name="skill"/>
		</union-subclass>
		
		<union-subclass name="Saler" table="saler">
			<property name="age"/>
			<property name="sale"/>
		</union-subclass>
	</class>

注意,这里主键的生成方式就不能是自增的了,这里用的hilo方式,可以为子类的表分配和父类的表不同的主键。这样每个子类生成了一个表,并且结合了父类中的属性。生成的表的ddl语句为:

CREATE TABLE `skiller` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `depart_id` int(11) DEFAULT NULL,
  `skill` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK4AFD4ACE972E06147ffd86be` (`depart_id`),
  CONSTRAINT `FK4AFD4ACE972E06147ffd86be` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

注意,这里的外键是部门类对应的表的主键,这是和上面两个标签的区别之处。若是将父类设置为抽象类,并且在class标签中设置abstract="true",那么父类就不会生成对应的表了。




标签:hibernate,标签,subclass,主键,子类,父类,id
From: https://blog.51cto.com/u_5173797/7251402

相关文章

  • hibernate——多对一和一对多映射浅析
    首先应该清楚多对一和一对多只是站在不同的角度看待问题,其本质是一样的。在思考这个问题的时候,不要把这两个概念混在一起,这样不容易理解,而要分开,站在不同的角度去解决同一个问题。就拿员工和部门的例子来说,我们站在不同的角度,可能会遇到如下的几种情况:站在员工的角度看,是多对一的关......
  • hibernate——简单的增删改查
    增删改比较简单,查稍微复杂一点。查询有两种方式,一种是通过hql语句和Query接口来实现,一种是条件查询,通过Ctiteria接口来实现,下面举例说明:UserDao接口:packagecom.suo.hibernate.dao;importjava.util.List;importcom.suo.domain.User;publicinterfaceUserDao{ publicv......
  • hibernate——Session接口中定义的saveOrUpdate()方法浅析
    Session接口中定义的saveOrUpdate方法,集合了save和update方法,根据对象的状态来选择是进行保存还是更新,那它是怎么判断当前对象的状态的呢?API中对这个方法是这样说的,它是根据一个unsaved-value来决定的。这个值是在映射文件中的<id>标签中的一个属性。<id>标签表示的是表的主键,若主......
  • hibernate——初步认识
    开始学习hibernate了,跟着网上的教学视频边看边学。现在有些迷茫,不知道学这些东西,以后能不能用得上,也不知道未来会发展成什么样子,也不知道我的基础算是打好了没有,总觉得学这些框架,有点浮沙筑高台的感觉,心里很不踏实。知道的都是些表面的东西,框架底层是什么样的,看看那些源代码,想看懂......
  • hibernate——两种查询方式
    一种是hql语句查询,用Query接口去实现;一种是条件查询,用Criteria接口去实现。这两种方式作用差不多,只是后者更符合面向对象一些。用hql语句查询,如下例:publicstaticvoidquery(Stringname){ Sessionsession=null; try{ session=HibernateUtil.getSession(); //St......
  • hibernate——和数据库关联的对象的三种状态
    和数据库关联的对象有三种状态:瞬时,持久,脱管。瞬时:在数据库中还没有与该对象关联的记录,仅仅是一个普通的对象而已,超过作用域,就会被回收。一般都是new出来的对象,并且还没有与session建立联系。持久:与session建立了联系,并且在数据库中已经有了和该对象关联的记......
  • hibernate——一对一、多对一和多对多关系的比较
    现在学习完了这几种映射关系,但是有点乱,这里来小结一下。关键是表之间如何产生映射关系,以及产生的表的结构。1、一对一映射:一对一是通过one-to-one标签来产生映射关系的,其实,如果单单说是建立两个表之间的关联,只要在一个映射文件中配置one-to-one标签就可以了,在另一个映射文件中,也做......
  • 如何更改轴标签的方向?
    https://excel.dovov.com/1741.htmlvv 这将改变X轴刻度标签的方向。ActiveChart.Axes(xlCategory).TickLabels.Orientation=45'degrees 这是如何改变轴标题的方向:ActiveChart.Axes(xlCategory).AxisTitle.Orientation=81'degrees你有没有试过录制macros?......
  • 百易CMS常用标签
    百易CMS是一款免费开源的phpcms系统下面我将分享他常用的标签系统!页头常用标签{baiyi.site.title}{baiyi.site.keywords}{baiyi.site.description}{baiyi.site.tpl}模板路径解析为/template/pc不含/横杠栏目调用方式(多个栏目){baiyi:nav}标签为调用栏目内容支持参数有id......
  • discuz3.4,关于安装dev8133插件(购买帖子内容),在论坛对用户组开启评分功能后,用户一点击
    漏洞修补方案一:后端措施在source/module/forum/forum_misc.php文件中,$post=C::t('forum_post')->fetch('tid:'.$_G['tid'],$_GET['pid']);//这一步调用大C的静态方法t()从表forum_post中根据tid和pid共同查询出当前要评分的帖子主体内容对此处查询出来的$post数据直接后端进......