Hibernate上路_16-继承关系映射

例:员工Employee分为正式工SalaryEmployee和临时工HourEmployee。子类表的字段都不能使用非空约束。

1.三种继承关系的建表方式:

1)父类、子类在同一张表,表中有“辨别者列”。通过辨别者列值,区分父类数据和子类数据。
2)父类、子类各一张表。将公共数据放入父表,将个体数据存放子表,子表通过外键关联父表的公共数据。
3)父子类分别建表,父子表无关联,将父类数据存放到父类表,将子类数据存放子类表 ,父子表采用连续增长主键 

2.subClass方式:

父子类数据在同一张表,引入辨别者列(discriminator)用来区分数据记录是父类还是子类。

1)父子类POJO

Hibernate上路_16-继承关系映射


2)父类.hbm.xml配置:

对于继承关系映射,不需要为每个类建立hbm文件。只需要针对父类编写hbm即可。

<hibernate-mapping package="cn.cvu.hibernate.domain">
	<!-- 0.父类、子类都要配置辨别值,将在辨别者列中存储 -->
	<class name="PojoHuman" table="tb_human" select-before-update="true" 
  discriminator-value="human">
		<id name="id" column="t_id" type="int">
			<generator class="native" />
		</id>
		<!-- 1.首先配置辨别者列! 
			column="自定义列名"
			type="自定义类型"  -->
		<discriminator column="t_disc" type="string"/>
		
		<!-- 2.然后配置父类的通用属性! -->
		<property name="name" column="t_name" />
		
		<!-- 3.最后配置子类关系 
			name="子类全路径" -->
		<subclass name="cn.cvu.hibernate.domain.PojoWoman" discriminator-value="woman">
			<!-- 子类的个体属性 -->
			<property name="waistline"/>
			<property name="beauty"/>
		</subclass>
		<subclass name="cn.cvu.hibernate.domain.PojoMan" discriminator-value="man">
			<property name="height"/>
			<property name="beauty"/>
		</subclass>
	</class>
</hibernate-mapping>


3)作为单表操作:

1)插入:

    public void test(){
		Session session = UtilGetSession.openSession();
		Transaction transaction = session.beginTransaction();
		
		PojoHuman human = new PojoHuman();
		human.setName("地球人");
		
		PojoWoman woman = new PojoWoman();
		woman.setName("女人");
		woman.setWaistline(36);
		woman.setBeauty("漂亮");
		
		PojoMan man = new PojoMan();
		man.setName("男人");
		man.setHeight(175);
		man.setSpeed(12);
		
		session.save(human);
		session.save(woman);
		session.save(man);
		
		transaction.commit();
		session.close();
	}

Hibernate上路_16-继承关系映射

(2)查询,通常使用HQL

                String hqlHuman="from PojoHuman";
                Query queryHuman = session.createQuery(hqlHuman);
                List listHuman = queryHuman.list();
                System.out.println(listHuman);


3.joined-subclass方式:

为每个父类和子类建立单独数据表,将公共数据放入父表, 将个体信息存入子表,子表通过外键与父表关联。

1)类结构相同:

2)父类.hbm.xml配置:

<hibernate-mapping package="cn.cvu.hibernate.domain">
	<class name="PojoHuman" table="tb_human" select-before-update="true">
		<id name="id" column="t_id" type="int">
			<generator class="native" />
		</id>
		
		<!-- 父类的通用属性  -->
		<property name="name" column="t_name" />
		
		<!-- 子类配置
		name="子类全路径"
		table="子类对应的表" -->
		<joined-subclass name="cn.cvu.hibernate.domain.PojoWoman" table="tb_woman">
			<!-- 子表主键,也是关联父表的外键 -->
			<key column="t_human_child"></key>
			<!-- 子类的个体属性 -->
			<property name="waistline"></property>
			<property name="beauty"></property>
		</joined-subclass>
		
		<joined-subclass name="cn.cvu.hibernate.domain.PojoMan" table="tb_man">
			<key column="t_human_child"></key>
			<property name="height"></property>
			<property name="speed"></property>
		</joined-subclass>
	</class>
</hibernate-mapping>


3)测试:

1)测试保存:
代码同上。
Hibernate上路_16-继承关系映射

2)测试查询:
同上。

3)测试删除: 

                PojoHuman human = new PojoHuman();
                human.setId(2);	//父类托管对象
                session.delete(human);

org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
WARN: SQL Error: 1451, SQLState: 23000 
org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
ERROR: Cannot delete or update a parent row: a foreign key constraint fails 
(`db_hibernate`.`tb_woman`, CONSTRAINT `FK_8n9ux8k3f9lja8fldi8om7cg0` FOREIGN KEY 
(`t_human_child`) REFERENCES `tb_human` (`t_id`)) 

4.union-subclass方式:

父类和子类单独建表,父表和子表无关联;父类数据插入父表,子类数据插入子表,父表和子表的主键连续自增。

注意:不能使用identitynative,因为需要在多张表完成主键连续自增;可以使用sequencemysql不支持)、 increment (hibernate实现,max(id)+1)

1)类结构相同:

2)父类.hbm.xml配置:

<hibernate-mapping package="cn.cvu.hibernate.domain">
	<class name="PojoHuman" table="tb_human" select-before-update="true">
		<id name="id" column="t_id" type="int">
			<generator class="increment" />
		</id>
		
		<!-- 父类的通用属性  -->
		<property name="name" column="t_name" />
		
		<!-- 子类配置
			name="子类全路径"
			table="子类对应的表" -->
		<union-subclass name="cn.cvu.hibernate.domain.PojoMan" table="tb_man">
			<!-- 子类属性 -->
			<property name="height"/>
			<property name="speed"/>
		</union-subclass>
		<union-subclass name="cn.cvu.hibernate.domain.PojoWoman" table="tb_woman">
			<property name="waistline"/>
			<property name="beauty"/>
		</union-subclass>
	</class>
</hibernate-mapping>


3)测试:

1)测试保存:

2)测试查询:

3)查询删除:


5.建表原则:

Hibernate上路_16-继承关系映射

如果父子类数据非常简单,可以使用subclass , 重点推荐joinedsubclass (性能最好),不推荐unionsubclass

- end
 

你可能感兴趣的:(sql,Hibernate,继承,jdbc,数据持久化)