hibernate继承映射关系 —— 每个具体类映射成一张表

8 篇文章 0 订阅
2 篇文章 0 订阅
本文介绍了一种ORM映射策略——“每个具体类一张表”,并详细展示了如何在Hibernate框架下实现这种策略。通过具体的Java代码示例,文章解释了如何为Person基类及其子类Student和Worker创建相应的数据库表。
摘要由CSDN通过智能技术生成

每个具体类一张表”的意思是:使继承体系中每一个子类都对应数据库中的一张表每一个子类对应的数据库表都包含了父类的信息,并且包含了自己独有的属性。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段。这种策略是使用<union-subclass>标签来定义子类的。



通过mysql建立worker表和student表


Person类:

package com.hiberbate.manytomany;
public class Person {
	private int id;
	private String name;
	private int age;
	private String sex;
	public int getId(){
		return id;
	}
	public void setId(int id){
		this.id = id;
	}
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}
	public int getAge(){
		return age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public String getSex(){
		return sex;
	}
	public void setSex(String sex){
		this.sex = sex;
	}
	
}

Student类:

package com.hiberbate.manytomany;
public class Student extends Person{
	private String sno;
	private String school;
	public String getSno(){
		return sno;
	}
	public void setSno(String sno){
		this.sno = sno;
	}
	public String getSchool(){
		return school;
	}
	public void setSchool(String school){
		this.school = school;
	}
}

Worker类:

package com.hiberbate.manytomany;
public class Worker extends Person{
	private String wno;
	private String salary;
	public String getWno(){
		return wno;
	}
	public void setWno(String wno){
		this.wno = wno;
	}
	public String getSalary(){
		return salary;
	}
	public void setSalary(String salary){
		this.salary = salary;
	}
}

父类映射文件tb_persons.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.hiberbate.manytomany">
    <class name="Person" table="tb_persons" abstract="true"><!-- 多设置一个属性abstract="true",因为根本就没有tb_persons表 -->  
        <id name="id" column="id" type="int" >
            <!-- 父类的主键生成策略为‘分配’ -->   
            <generator class="assigned" />  
        </id>
        <property name="name" type="string">
            <column name="name"/>
        </property>
		<property name="sex" type="string" column="sex"></property>
		<property name="age" type="int" column="age"></property>
		
		<!--student具体类-->    
	    <union-subclass name="Student" table="tb_student">    
	        <property column="sno" name="sno" type="string"></property>      <!-- 特征属性 -->   
	        <property column="school" name="school" type="string"></property>  <!-- 特征属性 -->  
	    </union-subclass>    
	        
	    <!--worker具体类-->    
	    <union-subclass name="Worker" table="tb_worker">    
	        <property column="wno" name="wno" type="string"></property>  <!-- 特征属性 -->  
	        <property column="salary" name="salary" type="string"></property>  <!-- 特征属性 -->  
	    </union-subclass>    
    </class>
</hibernate-mapping>
<union-subclass>标签是用于指示出该hbm文件所表示的类的子类,如Person类有两个子 类,就需要两个<union-subclass>标签以此类推。

<union-subclass>标签的"name"属性用于指 定子类的全限定名称,"table"属性用于指定该子类对应的表的名称,"extends"属性用于指定该子类的父类,

注意:"extends"属性与<union-subclass>标签的位置有关,若<union-subclass>标签作为<class>标签的子标签,则"extends"属性可以不设置,否则需要明确设置"extends"属性。

<class>标签中的"abstract"属性如果值为true则,不会生成表结构。如果值为false则会生成表结构,但是不会插入数据。


测试代码:

HibernateUtil类在我的这篇博客《eclipse集成Hibernate5开发过程,配置问题,走过的坑,详细介绍》上面有,就不贴代码了

private static void joinsubclassforsave() {
	Session session = null;
		 //新建学生对象  
         Student stu = new Student();  
         stu.setId(9);  
         stu.setName("张三");  
         stu.setAge(new Integer(22));  
         stu.setSex("男");  
         stu.setSno("100120122016");  
         stu.setSchool("华中科技大学"); 
         
         //新建工人对象  
         Worker worker=new Worker();  
         worker.setId(101);  
         worker.setName("李四");  
         worker.setAge(26);  
         worker.setSex("男");  
         worker.setWno("W20121224");  
         worker.setSalary("8000"); 
		 
		 try {
  	        
  			session = HibernateUtil.getSession();
  			//添加数据
  			session.beginTransaction();
  			session.save(stu);
  			session.save(worker);
  			
  			session.getTransaction().commit();
  			
		 } catch (Exception e) {
			session.getTransaction().rollback();
			System.out.print("数据库添加失败");
			e.printStackTrace();
		 }finally{
			HibernateUtil.closeSession();
		 }
		
	}

注意:上面标红部分,如果id设置成一样,会有如下错误

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Tue Mar 06 15:24:28 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
数据库添加失败org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.hiberbate.manytomany.Worker#9]
	at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:169)
	at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
	at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
	at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
	at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
	at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
	at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
	at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:682)
	at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
	at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
	at com.book.web3.HibernateTest.joinsubclassforsave(HibernateTest.java:107)
	at com.book.web3.HibernateTest.main(HibernateTest.java:44)

这是由于在配置文件中 <union-subclass>标签中不需要key值了,而且Person的主键生成策略不能是自增(native)了,如果自增的话,Student表中第一条记录id为1,Worker表中第一条记录也为1,而它们在实际意义上属于同一类型(可以看做在一张表中),否则可能造成不同子类对应表中的主键相同,所以主键不可一致。

结果如图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值