1.当父类中拥有大量子类共有属性,子类拥有极少量子类特有属性
下面用Hibernate来完成这种继承关系的映射:
Employee类:(父类)省略get和set方法
/**
* 1.整个继承关系树对应一张表.-员工类
*/
public class Employee {
private Integer id;
private String name;
private Integer age;
}
HourEmployee类:继承父类 省略get和set方法
/**
* 临时工
*/
public class HourEmployee extends Employee {
private float rate ;
}
SalaryEmployee类:继承父类 省略get和set方法
/**
* 正式员工
*/
public class SalaryEmployee extends Employee {
private float salary ;
}
只要写一个Employee.hbm.xml映射文件即可:
<!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.xxc.domain.Employee" table="employee" lazy="false" discriminator-value="ee"><!-- discriminator-value="ee"父类在数据库中区分字段etype的值 -->
<id name="id" column="id" type="integer">
<generator class="identity"></generator>
</id>
<!-- 必须在 id后 ,用来设置数据库中区分子类种类的字段属性-->
<discriminator column="etype" type="string" length="2"/>
<property name="name" column="name" type="string"/>
<property name="age" column="age" type="integer"/>
<!-- 子类映射 discriminator-value="he"表示当前映射类在数据库中区分字段etype的值 -->
<subclass name="com.xxc.domain.HourEmployee" discriminator-value="he">
<property name="rate" column="rate" type="float"/><!-- 配置子类特有属性就行,不用再次配父类共有属性 -->
</subclass>
<subclass name="com.xxc.domain.SalaryEmployee" discriminator-value="se">
<property name="salary" column="salary" type="float"/>
</subclass>
</class>
</hibernate-mapping>
测试类:
public class App {
private static SessionFactory sf = null;
@BeforeClass
public static void initialize(){
Configuration config = new Configuration();
/* 也可以写成这样的形式
* sf = config.addClass(Customer.class).addClass(Order.class).buildSessionFactory();
*/
config.addClass(Employee.class);
sf = config.buildSessionFactory();
}
@Test
public void insert(){
Session session = sf.openSession();
Transaction t = session.beginTransaction();
Employee e = new Employee();
e.setName("ee");
HourEmployee he = new HourEmployee();
he.setName("he");
he.setRate(500);
SalaryEmployee se = new SalaryEmployee();
se.setName("se");
se.setSalary(1000);
session.save(e);
session.save(he);
session.save(se);
t.commit();
session.close();
}
@Test
public void find(){//查询子类,只需要将Form写子类类名即可。
Session session = sf.openSession();
Transaction t = session.beginTransaction();
List list = session.createQuery("FROM HourEmployee").list();
t.commit();
session.close();
}
}
2.当子类拥有较多子类特有属性
下面用Hibernate来完成这种继承关系的映射:
Employee和HourEmployee和SalaryEmployee三个类还是和上面一样定义,只改变了Employee.hbm.xml
Employee.hbm.xml:
<!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.xxc.b_domain.Employee" table="employee_join" lazy="false">
<id name="id" column="id" type="integer">
<generator class="identity"></generator>
</id>
<property name="name" column="name" type="string"/>
<property name="age" column="age" type="integer"/>
<!-- 连接到子类,子类自己也建表 -->
<joined-subclass name="com.xxc.b_domain.HourEmployee" table="hourEmployee_join">
<key column="eid"/><!-- 子类表中和父类表中有关联关系的数据库字段名 -->
<property name="rate" column="rate" type="float"/>
</joined-subclass>
<joined-subclass name="com.xxc.b_domain.SalaryEmployee" table="salaryEmployee_join">
<key column="eid"/>
<property name="salary" column="salary" type="float"/>
</joined-subclass>
</class>
</hibernate-mapping>
测试类:
public class App_b {
private static SessionFactory sf = null;
@BeforeClass
public static void initialize(){
Configuration config = new Configuration();
/* 也可以写成这样的形式
* sf = config.addClass(Customer.class).addClass(Order.class).buildSessionFactory();
*/
config.addClass(Employee.class);
sf = config.buildSessionFactory();
}
@Test
public void insert(){
Session session = sf.openSession();
Transaction t = session.beginTransaction();
Employee e = new Employee();
e.setName("ee");
HourEmployee he = new HourEmployee();
he.setName("he");
he.setRate(500);
SalaryEmployee se = new SalaryEmployee();
se.setName("se");
se.setSalary(1000);
session.save(e);
session.save(he);
session.save(se);
t.commit();
session.close();
}
@Test//查询子类或全部
public void find(){
Session session = sf.openSession();
Transaction t = session.beginTransaction();
/* 内连接和外连接的区别:补齐
* a表数据多,并多于b表且包含b表信息,a和b存在关联关系,
* 1.那么当进行内连接查询时,只会查询出b表和a表共有信息(内连接)
* 2.那么当进行外连接查询时,就会查询出a表中所有信息,a表中在b表中没有对应信息的数据也被查询出来
*/
String hql = "FROM HourEmployee";//因为是从子类,即从 从表开始查,那么就会内连接到主表,只查询出指定的子类的信息
hql = "FROM Employee";//因为是从父类,即从主表开始出巡,那么就会外连接到从表,查询出所有信息,包括子类没有的
List list = session.createQuery(hql).list();
t.commit();
session.close();
}
@Test//只是查询父类
public void findFather(){
Session session = sf.openSession();
Transaction t = session.beginTransaction();
//查询id既不在HourEmployee又不在SalaryEmployee
String hql = "FROM Employee e WHERE e.id NOT IN(SELECT id FROM HourEmployee) AND e.id NOT IN(SELECT id FROM SalaryEmployee)";
List list = session.createQuery(hql).list();
t.commit();
session.close();
}
}
3.联合查询UNION
Employee和HourEmployee和SalaryEmployee三个类还是和上面一样定义,只改变了Employee.hbm.xml,测试类也和上面一样。
<!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.xxc.c_domain.Employee" table="employee_union" lazy="false">
<id name="id" column="id" type="integer">
<generator class="hilo"><!-- 需要用hilo主键生成策略 -->
<param name="table">hilos</param><!-- 设置存放id字段的表名 -->
<param name="column">currentid</param><!-- 设置存放id的字段名 -->
<param name="max_lo">10</param><!-- 设置步长 -->
</generator>
</id>
<property name="name" column="name" type="string"/>
<property name="age" column="age" type="integer"/>
<!-- 联合子类union -->
<union-subclass name="com.xxc.c_domain.HourEmployee" table="HourEmployee_union">
<property name="rate" column="rate" type="float"/>
</union-subclass>
<union-subclass name="com.xxc.c_domain.SalaryEmployee" table="SalaryEmployee_union">
<property name="salary" column="salary" type="float"/>
</union-subclass>
</class>
</hibernate-mapping>