通过这种继承策略,我们可以通过单表映射整个层次结构。 这里,在表中创建一个额外的列(也称为discriminator
列)来标识该类。
让我们先了解问题。下面给出的整个层次类映射到数据库的一个表中图解说明。
这个层次结构中有三个类。employee
是regular_employee
和contract_employee
类的超类(父类)。 让我们来看看这个层次结构类的映射文件。
<?xml version='1.0' encoding='utf-8'?>
<!doctype hibernate-mapping public
"-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.h3.employee" table="emp121"
discriminator-value="emp">
<id name="id">
<generator class="increment"></generator>
</id>
<discriminator column="type" type="string"></discriminator>
<property name="name"></property>
<subclass name="com.h3.regular_employee"
discriminator-value="reg_emp">
<property name="salary"></property>
<property name="bonus"></property>
</subclass>
<subclass name="com.h3.contract_employee"
discriminator-value="con_emp">
<property name="pay_per_hour"></property>
<property name="contract_duration"></property>
</subclass>
</class>
</hibernate-mapping>
在每个类层次结构一个表的情况下,hibernate框架添加了一个标识符列,该框架指定了记录的类型。 它主要用于区分记录。要指定它,必须指定类的 discriminator
子元素。
类的子类subelement
指定子类。 在这种情况下,regular_employee
和contract_employee
是employee
类的子类。
此层次结构的表结构如下所示:
列名 | 数据类型 | 是否为空 | 默认值 | 是否主键 |
---|---|---|---|---|
id | int(10) | 否 | - | 是 |
type | varchar(254) | 否 | - | - |
name | varchar(254) | 是 | - | - |
salary | float | 是 | - | - |
bonus | int(10) | 是 | - | - |
pay_per_hour | float | 是 | - | - |
contract_duration | 是 | - | - |
在这个例子中,我们创建了三个类,并在employee.hbm.xml
文件中提供了这些类的映射。
完整的工程目录如下所示 -
下载代码的项目名称:table-per-hierarchy-example-using-xml-file
您需要创建表示继承的持久化类。让我们为上面的层次结构创建三个类:
文件: employee.java
package com.h3;
public class employee {
private int id;
private string name;
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;
}
}
文件: regular_employee.java
package com.h3;
public class regular_employee extends employee {
private float salary;
private int bonus;
public float getsalary() {
return salary;
}
public void setsalary(float salary) {
this.salary = salary;
}
public int getbonus() {
return bonus;
}
public void setbonus(int bonus) {
this.bonus = bonus;
}
}
文件: contract_employee.java
package com.h3;
public class contract_employee extends employee {
private float pay_per_hour;
private string contract_duration;
public float getpay_per_hour() {
return pay_per_hour;
}
public void setpay_per_hour(float payperhour) {
pay_per_hour = payperhour;
}
public string getcontract_duration() {
return contract_duration;
}
public void setcontract_duration(string contractduration) {
contract_duration = contractduration;
}
}
上面我们已经了解了层次结构,下面来看看如何配置映射文件。
文件: employee.hbm.xml
<?xml version='1.0' encoding='utf-8'?>
<!doctype hibernate-mapping public
"-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.h3.employee" table="emp121"
discriminator-value="emp">
<id name="id">
<generator class="increment"></generator>
</id>
<discriminator column="type" type="string"></discriminator>
<property name="name"></property>
<subclass name="com.h3.regular_employee"
discriminator-value="reg_emp">
<property name="salary"></property>
<property name="bonus"></property>
</subclass>
<subclass name="com.h3.contract_employee"
discriminator-value="con_emp">
<property name="pay_per_hour"></property>
<property name="contract_duration"></property>
</subclass>
</class>
</hibernate-mapping>
打开hibernate.cfg.xml
文件,并添加如下映射资源的条目:
<mapping resource="employee.hbm.xml"/>
现在配置文件将如下所示:
文件:hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!doctype hibernate-configuration public
"-//hibernate/hibernate configuration dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- generated by myeclipse hibernate tools. -->
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="connection.driver_class">com.mysql.jdbc.driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="dialect">org.hibernate.dialect.mysql5innodbdialect</property>
<property name="show_sql">true</property>
<mapping resource="employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
hbm2ddl.auto
属性定义是用于在数据库中创建自动表。
在这个类中,我们只是将employee
对象存储到数据库表中。
文件:storedata.java
package com.h3;
import org.hibernate.*;
import org.hibernate.boot.metadatasources;
import org.hibernate.boot.registry.standardserviceregistry;
import org.hibernate.boot.registry.standardserviceregistrybuilder;
import org.hibernate.cfg.*;
public class storedata {
public static void main(string[] args) {
// session session = new
// annotationconfiguration().configure().buildsessionfactory().opensession();
final standardserviceregistry registry = new standardserviceregistrybuilder()
.configure("hibernate.cfg.xml").build();
// 2. 根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
sessionfactory sessionfactory = new metadatasources(registry)
.buildmetadata().buildsessionfactory();
/**** 上面是配置准备,下面开始我们的数据库操作 ******/
session session = sessionfactory.opensession();// 从会话工厂获取一个session
transaction t = session.begintransaction();
employee e1 = new employee();
e1.setname("h3");
regular_employee e2 = new regular_employee();
e2.setname("max su");
e2.setsalary(50000);
e2.setbonus(5);
contract_employee e3 = new contract_employee();
e3.setname("hippo su");
e3.setpay_per_hour(1000);
e3.setcontract_duration("15 hours");
session.persist(e1);
session.persist(e2);
session.persist(e3);
t.commit();
session.close();
system.out.println("success");
}
}
运行上面程序,并打数据库表查看执行结果。