一、每个子类对应一个数据表(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
;
/**
default
constructor
*/
public
Person() {
}
public
Long getId() {
return
this
.
id
;
}
public
void
setId(Long id) {
this
.
id
= id;
}
public
String getName() {
return
this
.
name
;
}
public
void
setName(String name) {
this
.
name
= name;
}
}
子类分别实现它,并添加额外的属性和相应
gettter
和
setter
方法。
如
Student
类:
public
class
Student
extends
Person {
private
Float
score
;
public
Student() {
super
();
}
public
Float getScore() {
return
score
;
}
public
void
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
,
primary
key
(`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
类
public
class
Person
implements
java.io.Serializable {
private
Long
id
;
private
String
name
;
private
Contact
contact
;
}
Contact
类
public
class
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
public
class
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
》一书