关于以前写的hibernate继承关系映射,当30多张表的时候,系统开销太大,导致了内存溢出的严重问题,没有办法,只能换一种继承策略了。
就是30多张表的共用字段都提取出来,在数据库里建一张表,其他表里只有自身的字段。然后在配置文件里面去继承共用的那张表就OK了。其间,只是一些配置文件的细节发生了变化。程序代码一点都不用改变!hibernate真强大啊!说多了没用,上代码!哦。。。先说说例子的大概情况:有一张职员表(这张表就是共用字段),一张小时工表(继承职员表),一张薪水工表(也继承职员表)。
(1)职员表
package mypack;
import java.io.Serializable;

public abstract class Employee implements Serializable ...{
private Long id;
private String name;
生成get、set方法
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<class name="mypack.Employee" table="EMPLOYEES" polymorphism="implicit">
<id name="id" type="long" column="ID">
<generator class="native"/>
</id>
<property name="name" type="string" column="NAME" />
</class>
</hibernate-mapping>
(2)小时工表
package mypack;
import java.io.Serializable;

public class HourlyEmployee extends Employee...{
private double rate;

/** *//** default constructor */
public HourlyEmployee() ...{
}

public double getRate() ...{
return this.rate;
}

public void setRate(double rate) ...{
this.rate = rate;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<joined-subclass name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES" extends="mypack.Employee" >
<key column="EMPLOYEE_ID" />
<property name="rate" column="RATE" type="double" />
</joined-subclass>
</hibernate-mapping>
(3)薪水工表
package mypack;
import java.io.Serializable;

public class SalariedEmployee extends Employee ...{
private double salary;

/** *//** default constructor */
public SalariedEmployee() ...{
}

public double getSalary() ...{
return this.salary;
}

public void setSalary(double salary) ...{
this.salary = salary;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<joined-subclass name="mypack.SalariedEmployee" table="SALARIED_EMPLOYEES" extends="mypack.Employee" >
<key column="EMPLOYEE_ID" />
<property name="salary" column="SALARY" type="double" />
</joined-subclass>
</hibernate-mapping>
最后一步:注意了!把职员表重新命名再映射一遍,这回不是抽象的了。
package mypack;
import java.io.Serializable;

public class jEmployee implements Serializable ...{
private Long id;
private String name;
private String type;

/** *//** default constructor */
public jEmployee() ...{
}
//生成get,set方法
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
<class name="mypack.jEmployee" table="EMPLOYEES" >
<id name="id" type="long" column="ID">
<generator class="native"/>
</id>
<property name="name" type="string" column="NAME" />
<property name="type" type="string" column="type" length="50"/>
</class>
</hibernate-mapping>一会说,接着说。
职位表中的type字段记录着每个子表的表名。
上面2,3的配置文件采用joined-subclass,hiberntae中的继承有3中,还有两种,一个是union-subclass和subclass。用union-subclass生成的sql语句都是以union形式的,用join-subclass生成的sql语句都是什么什么join。subclass这个方式太简单了,不说了。
为什么把职位表映射两遍呢?而且最后一遍的映射是没有继承关系的单一文件,而且也不是抽象的。因为hibernate继承映射的话,它会查出它子类的所有的东西,hibernate3.0是这样的。假如说我程序里面想把所有共性的字段以列表的形式查出来,那么hibernate就会把它的子类都查出来,这样开销太大了。所以把员工表单独映射一个纯净的类来解决这个开销问题。
关于(1)中的配置文件中的polymorphism="implicit"属性,有两个值,即:implicit (隐式)和explicit(显式)两种。默认是implicit。很多人说,把这个属性值设一下,这样按着父类查询是就不会把子类查出来,这是不对的,这种说法并没有理解隐式和显式的真正含义。他们的区别如下:
implicit(隐式)形式不使用join关键字。关联使用"点号"来进行“引用”。implicit join可以在任何HQL子句中出现.implicit join在最终的SQL语句中以inner join的方式出现。
from Cat as cat where cat.mate.name like '%s%'
Implicit (隐式)的多态是指,如果查询中给出的是任何超类、该类实现的接口或者该类的名字,都会返回这个类的实例;如果查询中给出的是子类的名字,则会返回子类的实例。 Explicit (显式)的多态是指,只有在查询中给出的明确是该类的名字时才会返回这个类的实例;同时只有当在这个<class>的定义中作为<subclass>或者<joined-subclass>出现的子类,才会可能返回。 大多数情况下,默认的polymorphism="implicit"都是合适的。 显式的多态在有两个不同的类映射到同一个表的时候很有用。(允许一个“轻型”的类,只包含部分表字段)。
Hibernate继承映射优化
针对Hibernate处理大量表时出现的内存溢出问题,通过优化继承策略解决了系统开销过大的难题。具体做法是将共有字段抽取到一张独立的表中,并调整了配置文件。
287

被折叠的 条评论
为什么被折叠?



