hibernate单表继承映射

hibernate支持三种基本的继承映射策略:

1、每个类分层结构一张表映射

2、每个子类一张表映射

3、每个具体类一张表映射

我们先来分析第一种策略,假设有一个父类Person,它有两个子类Teacher和Student,都继承了Person类,如图:


我们可以把这种关系的数据,设计到一张表中展示,如图:


下面我们来看下怎样来实现实体类和对应的映射关系来生成这张表。

Person类:

public class Person {
	private int id;
	private String name;
	private int age;
	//省略get/set
}
Teacher类:

public class Teacher extends Person{
	private int salary;
	public int getSalary() {
		return salary;
	}
	public void setSalary(int salary) {
		this.salary = salary;
	}
}
Student类:

public class Student extends Person{
	private String work;
	public String getWork() {
		return work;
	}
	public void setWork(String work) {
		this.work = work;
	}
}
Person.hbm.xml配置文件

<hibernate-mapping package="com.test.pojo">
	<class name="Person">
		<id name="id">
			<generator class="native"></generator>
		</id>
		<!-- discriminator指明鉴别器
		     column:数据库表字段,用来区分不同的子类subclass,具体的数值,来源于不同的subclass中的discriminator-value
		 -->
		<discriminator column="type" type="string" />
		<property name="name" />
		<property name="age" />
		<subclass name="Student" discriminator-value="s">
			<property name="work" />
		</subclass>
		<subclass name="Teacher" discriminator-value="t">
			<property name="salary" />
		</subclass>
	</class>
</hibernate-mapping>

HibernateUtil类

public class HibernateUtil {
	private static Configuration cfg=null;
	private static SessionFactory factory=null;
	private static Session session=null;
	static{
		cfg=new Configuration().configure();
		factory=cfg.buildSessionFactory(new StandardServiceRegistryBuilder()
		.applySettings(cfg.getProperties()).build());
	}
	public static Session getSession(){
		if(factory!=null)
			return session=factory.openSession();
		factory=cfg.buildSessionFactory(new StandardServiceRegistryBuilder()
		.applySettings(cfg.getProperties()).build());
		return session=factory.openSession();
	}
	public static void closeSession(){
		if(session!=null && session.isOpen())
			session.close();
	}
}
hibernate.cfg.xml配置文件

<hibernate-configuration>
<session-factory>
	<!-- 数据库配置信息 -->
	<property name="connection.driver_class">
		com.mysql.jdbc.Driver
	</property>
	<property name="connection.url">
		jdbc:mysql:///hibernatetest
	</property>
	<property name="connection.username">root</property>
	<property name="connection.password">root</property>
	<!-- 数据库方言 -->
	<property name="dialect">
		org.hibernate.dialect.MySQLDialect
	</property>
	<property name="show_sql">true</property>
	<property name="format_sql">true</property>
	<!-- 映射文件 -->
	<mapping resource="com/test/pojo/Person.hbm.xml" />
</session-factory>
</hibernate-configuration>

测试类

public class HibernateTest {
	@Test
	public void testCreateDB(){
		Configuration cfg=new Configuration().configure();
		SchemaExport se=new SchemaExport(cfg);
		//第一个参数表示是否生成ddl脚本,第二个参数表示是否执行到数据库中
		se.create(true, true);
	}
	/**
	 * 保存数据
	 */
	@Test
	public void save(){
		Session session=null;
		Transaction tx=null;
		try{
			session=HibernateUtil.getSession();
			tx=session.beginTransaction();
			Teacher teacher=new Teacher();
			teacher.setName("teacher");
			teacher.setAge(20);
			teacher.setSalary(5000);
			Student student=new Student();
			student.setName("stu1");
			student.setAge(20);
			student.setWork("hello world");
			Student stu=new Student();
			stu.setName("stu2");
			stu.setAge(21);
			stu.setWork("Struts2");
			session.save(student);
			session.save(stu);
			session.save(teacher);
			tx.commit();
		}catch(Exception e){
			if(tx!=null)
				tx.rollback();
			e.printStackTrace();
		}finally{
			HibernateUtil.closeSession();
		}
	}
	@Test
	public void testGet(){
		Session session=null;
		Transaction tx=null;
		try{
			session=HibernateUtil.getSession();
			tx=session.beginTransaction();
			//取数据。
			//查询数据时,如果使用get查询得到的数据类型可以进行多态判断。如果通过load(lazy)查询,不能判断。
			Person person=(Person) session.get(Person.class, 2);
			System.out.println(person.getName());
			if(person instanceof Student){
				Student stu=(Student) person;
				System.out.println(stu.getWork());
			}
			tx.commit();
		}catch(Exception e){
			tx.rollback();
			e.printStackTrace();
		}finally{
			HibernateUtil.closeSession();
		}
	}
}
结果可自己运行查看。

总结:

1、在单表继承映射中,hibernate通过鉴别器来识别子类的类型。鉴别器由hibernate来进行维护。

2、查询数据时,如果使用get查询得到的数据类型可以进行多态判断;如果使用load查询,load是懒加载(lazy),返回的是代理类,不能进行判断。

3、Person.hbm.xml中子类的配置还有一种形式:就是将subclass放到class同级目录下,但必须指明继承自那个类。如图:
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值