|
一、每个子类对应一个数据表(table per concrete class) 学生表 create table `sample`.`student`( `id` bigint not null auto_increment, `name` varchar(20) default '' not null, `score` float, primary key (`id`) ); create unique index `primary` on `sample`.`student`(`id`); 教师表 create table `sample`.`teacher`( `id` bigint not null auto_increment, `name` varchar(20) default '' not null, `salary` float(6,2), primary key (`id`) ); create unique index `primary` on `sample`.`teacher`(`id`); person抽象基类 public abstract class person implements java.io.serializable { private long id; private string name; /**defaultconstructor*/ public person() { } public long getid() { returnthis.id; } publicvoid setid(long id) { this.id = id; } public string getname() { returnthis.name; } publicvoid setname(string name) { this.name = name; } } 子类分别实现它,并添加额外的属性和相应gettter和setter方法。 如student类: public class student extends person { private float score; public student() { super(); } public float getscore() { returnscore; } publicvoid setscore(float score) { this.score = score; } } 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"> <hibernate-configuration> <session-factory> <property name="connection.username">root</property> <property name="connection.url"> jdbc:mysql://localhost:3306/sample </property> <property name="dialect"> org.hibernate.dialect.mysqldialect </property> <property name="connection.password">12345678</property> <property name="connection.driver_class"> com.mysql.jdbc.driver </property> <property name="show_sql">true</property> <property name="current_session_context_class">thread</property> <mapping resource="powerwind/bean/student.hbm.xml" /> <mapping resource="powerwind/bean/teacher.hbm.xml" /> </session-factory> </hibernate-configuration> 由于person抽象类没有对应数据库的表,也没有对应的映射文件,在hql查询中也就不支持多态查询。感觉上,person抽象类的作用只是减少java代码的编写而已。
二、每个类对应一个表(table per subclass) 人员表 create table `sample`.`person`( `id` bigint not null auto_increment, `name` varchar(20), primary key (`id`) ); 学生表 create table `sample`.`student`( `id` bigint default '' not null, `score` float, primarykey (`id`) ); 教师表 create table `sample`.`teacher`( `id` bigint default '' not null, `salary` float, primary key (`id`) ); 两个子类的实现和前一种完全一样, person类也只是去掉abstract修饰符而已。映射文件只需要person.hbm.xml一个即可。 <hibernate-mapping> <class name="powerwind.bean.person" table="person" catalog="sample"> <id name="id" type="java.lang.long"> <column name="id" /> <generator class="native"></generator> </id> <property name="name" type="java.lang.string"> <column name="name" length="20" not-null="true" /> </property> <joined-subclass name="powerwind.bean.student" table="student"> <key column="id" /> <property name="score" type="java.lang.float"> <column name="score" precision="12" scale="0" /> </property> </joined-subclass> <joined-subclass name="powerwind.bean.teacher" table="teacher"> <key column="id" /> <property name="salary" type="java.lang.float"> <column name="salary" precision="12" scale="0" /> </property> </joined-subclass> </class> </hibernate-mapping> 这种方式是支持多态查询的。 多态查询语句:query query=sdao.getsession().createquery("from person"); 三、一个表对多个类(table per class hierarchy) 人员表 create table `sample`.`person`( `id` bigint not null auto_increment, `name` varchar(20), `score` float, `salary` float, `type` char(1), primary key (`id`) ); person.hbm.xml <hibernate-mapping> <class name="powerwind.bean.person" table="person" catalog="sample"> <id name="id" type="java.lang.long"> <column name="id" /> <generator class="native"></generator> </id> <discriminator column="type" type="java.lang.string" /> <property name="name" type="java.lang.string"> <column name="name" length="20" not-null="true" /> </property> <subclass name="powerwind.bean.student" discriminator-value="s"> <property name="score" type="java.lang.float" /> </subclass> <subclass name="powerwind.bean.teacher" discriminator-value="t"> <property name="salary" type="java.lang.float" /> </subclass> </class> </hibernate-mapping> 优点是单表查询,支持多态;缺点是要在表增加字段(type)用于区分子类。
附加:实体粒度设计 1、面向设计的细粒度 人员表 create table `sample`.`person`( `id` bigint not null auto_increment, `name` varchar(20), `email` varchar(50), `phone` varchar(20), primary key (`id`) ); person类 publicclass person implements java.io.serializable { private long id; private string name; private contact contact; } contact类 publicclass contact implements java.io.serializable { private string email; private string phone; } 注:以上两个类的代码省略了getter和setter方法。 person.hbm.xml <hibernate-mapping> <class name="powerwind.bean.person" table="person" catalog="sample"> <id name="id" type="java.lang.long"> <column name="id" /> <generator class="native"></generator> </id> <property name="name" type="string" column="name"/> <component name="contact" class="powerwind.bean.contact"> <property name="email" type="string" column="email"/> <property name="phone" type="string" column="phone"/> </component> </class> </hibernate-mapping> 这样的细粒度,有什么用呢?应该在处理比较复杂表结构才体现出来吧。 2、面向性能的细粒度 假如contact类包含的字段是重量级的数据,如图片之类,而我们一般可能只需要一些简单的信息摘要。要怎么做呢? create table `sample`.`person`( `id` bigint not null auto_increment, `name` varchar(20), `gender` varchar(2), `email` varchar(50), `phone` varchar(20), primary key (`id`) ); 首先定义个基类baseperson publicclass baseperson { private long id; private string name; } person类继承baseperson类,添加多一个gender属性。 persondetail类继承person类,添加多一个email和phone属性。 person.hbm.xml <class name="powerwind.bean.person" table="person" catalog="sample"> <id name="id" type="java.lang.long"> <column name="id" /> <generator class="native"></generator> </id> <property name="name" type="string" column="name"/> <property name="gender" type="string" column="gender"/> </class> persondetail.hbm.xml <class name="powerwind.bean.persondetail" table="person" catalog="sample" polymorphism="explicit"> <id name="id" type="java.lang.long"> <column name="id" /> <generator class="native"></generator> </id> <property name="name" type="string" column="name" /> <property name="gender" type="string" column="gender" /> <property name="phone" type="string" column="phone" /> <property name="email" type="string" column="email" /> </class> 除了polymorphism="explicit"这一句,和每个子类对应一个数据表的继承关系没有什么区别。正是这句设置,去除了对persondetail的隐式多态查询。 query query=getsession().createquery("from person"); query query=getsession().createquery("from persondetail"); 上面两句中,第一句并不会查询到persondetail 对象,即查询字段不包括email和phone。 注:参考《深入浅出hibernate》一书
|