Hibernate学习笔记----映射继承关系

本文介绍Hibernate中三种不同的继承映射策略:subclass、joined-subclass和union-subclass,并对比了各自的优缺点。通过示例代码展示了如何实现每种映射方式。

用subclass映射继承关系

Person.java

package cn.limbo.hibernate.subclass;

public class Person {
	
	private Integer id;
	private String name;
	private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
	
	

}
Student.java

package cn.limbo.hibernate.subclass;

public class Student extends Person{
	
	private String school;

	public String getSchool() {
		return school;
	}

	public void setSchool(String school) {
		this.school = school;
	}

	@Override
	public String toString() {
		return super.toString() + "Student [school=" + school + "]";
	}
}
Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-7-23 9:18:25 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="cn.limbo.hibernate.subclass">

    <class name="Person" table="PERSONS" discriminator-value="PERSON">
    
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        
        <!-- 配置辨别者列 -->
        <discriminator column="TYPE" type="string"></discriminator>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="age" type="java.lang.Integer">
            <column name="AGE" />
        </property>
        <!-- 映射子类student 使用subclass进行映射 -->
        <subclass name="Student" discriminator-value="STUDENT">
        		<property name="school" type="string" column="SCHOOL"></property> //string是小写哦
        </subclass>
        
    </class>
    
</hibernate-mapping>

注意没有Student.hbm.xml,因为两者在一张表内!!!

Junit.java

package cn.limbo.hibernate.subclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Junit {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init()
	{
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
				.applySettings(configuration.getProperties()).build();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	@After
	public void destroy()
	{
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	//缺点:1.使用了辨别者列
	//	   2.子类独有的字段不能添加非空约束
	//     3.若继承层次较深,数据表的字段也较多
	
	/**
	 * 插入操作:
	 * 1.对于子类对象只需要把记录插到一张数据表中
	 * 2.辨别者列由hibernate自动维护
	 */
	
	@Test
	public void testSave()
	{
		Person person = new Person();
		person.setAge(11);
		person.setName("AA");
		
		session.save(person);
		
		Student student = new Student();
		student.setAge(22);
		student.setName("BB");
		student.setSchool("HZNU");
		session.save(student);
	}
	
	/**
	 * 查询:
	 * 1.查询父类记录只需要查询一张表就好了
	 * 2.对于子类记录也只需要查询一张数据表
	 */
	
	@Test
	public void testGet()
	{
		List<Person> persons = session.createQuery("FROM Person").list();//createQuery()方法使用时hql语句,返回一个List
		System.out.println(persons);
		
		List<Student> students = session.createQuery("FROM Student").list();
		System.out.println(students);
	}
}

用joined-subclass映射继承关系

Person.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-7-23 9:18:25 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="cn.limbo.hibernate.joined.subclass">

    <class name="Person" table="PERSONS">
    
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="age" type="java.lang.Integer">
            <column name="AGE" />
        </property>
        
        <joined-subclass name="Student" table="STUDENTS">
        		<key column="STUDENT_ID"></key>
        		<property name="school" type="string" column="SCHOOL"></property>
        </joined-subclass>
       
    </class>
    
</hibernate-mapping>
junit.class
package cn.limbo.hibernate.subclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Junit {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init()
	{
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
				.applySettings(configuration.getProperties()).build();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	@After
	public void destroy()
	{
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	//缺点:1.不需使用了辨别者列
	//	   2.子类独有的字段可以添加非空约束
	//     3.没有冗余的字段
	
	/**
	 * 插入操作:
	 * 1.对于子类对象至少要插入到两张数据表中
	 */
	
	@Test
	public void testSave()
	{
		Person person = new Person();
		person.setAge(11);
		person.setName("AA");
		
		session.save(person);
		
		Student student = new Student();
		student.setAge(22);
		student.setName("BB");
		student.setSchool("HZNU");
		session.save(student);
	}
	
	/**
	 * 查询:
	 * 1.查询父类记录:做一个左外连接查询
	 * 2.查询子类记录:做一个内连接
	 */
	
	@Test
	public void testGet()
	{
		List<Person> persons = session.createQuery("FROM Person").list();
		System.out.println(persons);
		
		List<Student> students = session.createQuery("FROM Student").list();
		System.out.println(students);
	}
}

用union-subclass映射继承关系

Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-7-23 9:18:25 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="cn.limbo.hibernate.union.subclass">

    <class name="Person" table="PERSONS">
    
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="hilo" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="age" type="java.lang.Integer">
            <column name="AGE" />
        </property>
        
        <union-subclass name="Student" table="STUDENTS">
        		<property  name="school" column="SCHOOL" type="string"></property>
        </union-subclass>
       
    </class>
    
</hibernate-mapping>

Junit.java

package cn.limbo.hibernate.union.subclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Junit {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init()
	{
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
				.applySettings(configuration.getProperties()).build();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	@After
	public void destroy()
	{
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	//优点:1.不需使用了辨别者列
	//	   2.子类独有的字段可以添加非空约束
	//缺点:1.存在冗余字段
	// 	   2.若更新父表的字段,更新效率较低
	
	/**
	 * 插入操作:
	 * 1.对于子类对象至少要插入到两张数据表中
	 */
	
	@Test
	public void testSave()
	{
		Person person = new Person();
		person.setAge(11);
		person.setName("AA");
		
		session.save(person);
		
		Student student = new Student();
		student.setAge(22);
		student.setName("BB");
		student.setSchool("HZNU");
		session.save(student);
	}
	
	/**
	 * 查询:
	 * 1.查询父类记录:需把父表和子表记录汇总到一起,性能稍差
	 * 2.查询子类记录:做一个内连接
	 */
	
	@Test
	public void testGet()
	{
		List<Person> persons = session.createQuery("FROM Person").list();
		System.out.println(persons);
		
		List<Student> students = session.createQuery("FROM Student").list();
		System.out.println(students);
	}
	
	@Test
	public void testUpdate()
	{
		String hql = "UPDATE Person p SET p.age = 20";
		session.createQuery(hql).executeUpdate();
	}
}

方式一:整个的继承体系就用一张表、

建立关系模型原则:描述一个继承关系只用一张表,也就是说子类所使用的表与父类相同

优缺点:首先表中引入的区分子类的字段,也就是包括了描述其他字段的字段。其次,如果某个子类的某个属性不能为空,那么在数据库一级不能设置该字段not null(非空),维护起来方便,只需要修改一个表,灵活性差,表中冗余字段会随着子类的增多而越来越多,在任何情况下,都只需处理一个表,对于单个对象的持久话操作只需要处理一个表

方式二:每个子类一张表,存放子类所特有的属性

建立关系模型原则:每个子类使用一张表,但这些子类所对应的表都关联到基类所对应的表中

优缺点:这种设计方式完全符合关系模型的设计原则,且不存在冗余,

维护起来比较方便,对每个类的修改只需要修改其所对应的表,灵活性很好,完全是参照对象继承的方式进行配置,对于父类的查询需要使用左外链接,对于子类查询需要使用内链接,对于子类的持久话至少要处理两个表

方式三:每个具体类一张表(union-subclass) ,保存是子类完整信息

建立关系模型原则:每个具体类对应一张表,有多少具体类就需要建立多少个独立的表

优缺点:这种设计方式符合关系模型的设计原则,但有表中存在重复字段的问题。如果需要对基类进行修改,则需要对基类以及该类的子类所对应的所有表都进行修改,映射的灵活性很大,子类可以包括基类属性在内的每一个属性进行单独配置,对于子类的查询只需要访问单独的表,对父类查询怎需要检索所有的表,对于单个对象持久话操作只需要处理一个表

但是讲道理,这个东西在开发中用到的情况很少




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值