hibernate应用中,继承的用途或目的主要有两点:

  • 组件化:故明思义,把重复性的代码抽取成组件,以便重用和维护。hibernate应用中,一些重复的字段,重复的映射配置,就需要抽取成组件。
  • 多态性:类的多态性是指下层业务所需一个父类对象,而上层业务根据所需的父类对象,传递一个子类对象。hibernate应用中,下层业务操作父类对象进行持久操作,如增删改查,上层业务则传递一个子类对象。

所以,在应用hibernate的继承时,需要明确设计所需,即究竟是组件化需求,还是多态性需求。

  • @MappedSuperclass:组件化需求的继承注解。虽然它可以应用于类的多态性业务中,但它不能应用于hibernate持久操作的多态性业务中。
  • @Inheritance:多态性需求的继承注解。虽然它可以达到组件化的目的,但它要比@MappedSuperclass多负出一些代价。

@MappedSuperclass定义:

@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface MappedSuperclass {
}

@Inheritance定义:

@Target({TYPE})
@Retention(RUNTIME)
public @interface Inheritance {
InheritanceType strategy() default SINGLE_TABLE;
}

InheritanceType定义:

public enum InheritanceType {
SINGLE_TABLE,
TABLE_PER_CLASS,
JOINED
}

从定义看出,@Inheritance的默认继承策略为SINGLE_TABLE,三种继承策略的区别在于:

  • SINGLE_TABLE:公共属性公共表,独立属性公共表。
    需要使用监别器区分具体的子类,注解@DiscriminatorColumn设置监别器列,注解@DiscriminatorValue设置监别器值。
    子类的属性映射配置时,需要设置为允许为空或默认值。
  • JOINED:公共属性公共表,独立属性独立表。
    子类的独立表生成后,其主键是一个共享主键,意味着这是一对一的关联,默认名称与父类的主键一致,使用注解@PrimaryKeyJoinColumn可改变名称。
  • TABLE_PER_CLASS:公共属性独立表,独立属性独立表。
    主键生成策略不能使用GenerationType.IDENTITY。

对于子类而言,公共属性就是父类的属性,公共表就是父类对应的表,而独立属性就是自己定义的属性,独立表就是自己对应的表。

示例1:继承注解@MappedSuperclass

User.java

@MappedSuperclass
public class User<ID extends Serializable> {
//---------------------------------------------------------------
// Field
//--------------------------------------------------------------- @Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private ID id; @Column(name = "loginName",
length = 20,
unique = true,
nullable = false,
updatable = false)
private String loginName; @Column(name = "loginPass",
length = 20,
nullable = false)
private String loginPass; //---------------------------------------------------------------
// Method
//--------------------------------------------------------------- public ID getId() {
return id;
} public void setId(ID id) {
this.id = id;
} public String getLoginName() {
return loginName;
} public void setLoginName(String loginName) {
this.loginName = loginName;
} public String getLoginPass() {
return loginPass;
} public void setLoginPass(String loginPass) {
this.loginPass = loginPass;
}
}

Admin.java

@Entity
@Table
public class Admin extends User<Integer> {
@Column(name = "role", length = 20, nullable = false)
private String role; public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
}
}

Member.java

@Entity
@Table
public class Member extends User<Long> {
@Column(name = "name", length = 20, nullable = false)
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

test.java

public class Test {
public static void main(String[] params){
// 继承注解:@MappedSuperclass
new Test().test();
/*
Hibernate:
drop table if exists Admin Hibernate:
drop table if exists Member Hibernate:
create table Admin (
id integer not null auto_increment,
loginName varchar(20) not null,
loginPass varchar(20) not null,
role varchar(20) not null,
primary key (id)
) Hibernate:
create table Member (
id bigint not null auto_increment,
loginName varchar(20) not null,
loginPass varchar(20) not null,
name varchar(20) not null,
primary key (id)
) Hibernate:
alter table Admin
add constraint UK_bdsh7mq6s6xad6ohm08u18uxr unique (loginName) Hibernate:
alter table Member
add constraint UK_jxtse8o1c6l89j39lilw5e2rs unique (loginName) Hibernate:
insert
into
Admin
(loginName, loginPass, role)
values
(?, ?, ?) Hibernate:
select
last_insert_id() Hibernate:
drop table if exists Admin Hibernate:
drop table if exists Member
*/
} public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass());
SessionFactory factory = null;
boolean success = true;
Session session = null;
try {
factory = (SessionFactory) context.getBean("sessionFactory");
session = factory.openSession();
success = false;
session.beginTransaction();
User<?> user = new Admin();
user.setLoginName("loginName");
user.setLoginPass("loginPass");
((Admin)user).setRole("role");
session.save(user);
session.getTransaction().commit();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
} if(factory != null){
factory.close();
factory = null;
}
}
}
}

示例2:继承注解@Inheritance,继承策略InheritanceType.SINGLE_TABLE。

User.java

@Entity
@Table
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "type",
discriminatorType = DiscriminatorType.STRING,
length = 30)
@DiscriminatorValue("User")
public class User {
//---------------------------------------------------------------
// Field
//--------------------------------------------------------------- @Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; @Column(name = "loginName",
length = 20,
unique = true,
nullable = false,
updatable = false)
private String loginName; @Column(name = "loginPass",
length = 20,
nullable = false)
private String loginPass; //---------------------------------------------------------------
// Method
//--------------------------------------------------------------- public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getLoginName() {
return loginName;
} public void setLoginName(String loginName) {
this.loginName = loginName;
} public String getLoginPass() {
return loginPass;
} public void setLoginPass(String loginPass) {
this.loginPass = loginPass;
}
}

Admin.java

@Entity
@DiscriminatorValue("Admin")
public class Admin extends User {
// 需要允许为空或设置默认值
@Column(name = "role", length = 20, nullable = true)
private String role; public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
}
}

Member.java

@Entity
@DiscriminatorValue("Member")
public class Member extends User {
// 需要允许为空或设置默认值
@Column(name = "name", length = 20, nullable = false, columnDefinition="VARCHAR(20) DEFAULT 'admin'")
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Test.java

public class Test {
public static void main(String[] params){
// 继承注解:@Inheritance
// 继承策略:InheritanceType.SINGLE_TABLE
// 公共属性公共表,独立属性公共表
new Test().test();
/*
Hibernate:
drop table if exists User Hibernate:
create table User (
type varchar(30) not null,
id bigint not null auto_increment,
loginName varchar(20) not null,
loginPass varchar(20) not null,
role VARCHAR(20) DEFAULT 'member' not null,
name VARCHAR(20) DEFAULT 'admin' not null,
primary key (id)
) Hibernate:
alter table User
add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate:
insert
into
User
(loginName, loginPass, role, type)
values
(?, ?, ?, 'Admin') Hibernate:
select
last_insert_id() Hibernate:
select
user0_.id as id2_0_0_,
user0_.loginName as loginNam3_0_0_,
user0_.loginPass as loginPas4_0_0_,
user0_.role as role5_0_0_,
user0_.name as name6_0_0_,
user0_.type as type1_0_0_
from
User user0_
where
user0_.id=? 多态性读取成功:study.t2.Admin@dc3aae Hibernate:
drop table if exists User
*/
} public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass());
SessionFactory factory = null;
try {
factory = (SessionFactory) context.getBean("sessionFactory"); // 多态性添加
boolean success = true;
Session session = null;
Long id = null;
try {
session = factory.openSession();
success = false;
session.beginTransaction();
User user = new Admin();
user.setLoginName("loginName");
user.setLoginPass("loginPass");
((Admin)user).setRole("role");
session.save(user);
session.getTransaction().commit();
id = user.getId();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
} // 多态性读取
if(success){
try {
session = factory.openSession();
session.beginTransaction();
success = false;
User user = session.load(User.class, id);
System.out.println("多态性读取成功:" + user);
session.getTransaction().commit();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
}
}
} finally {
if(factory != null){
factory.close();
factory = null;
}
}
}
}

示例3:继承注解@Inheritance,继承策略InheritanceType.JOINED。

User.java

@Entity
@Table
@Inheritance(strategy = InheritanceType.JOINED)
public class User { //---------------------------------------------------------------
// Field
//---------------------------------------------------------------
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; @Column(name = "loginName",
length = 20,
unique = true,
nullable = false,
updatable = false)
private String loginName; @Column(name = "loginPass",
length = 20,
nullable = false)
private String loginPass; //---------------------------------------------------------------
// Method
//--------------------------------------------------------------- public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getLoginName() {
return loginName;
} public void setLoginName(String loginName) {
this.loginName = loginName;
} public String getLoginPass() {
return loginPass;
} public void setLoginPass(String loginPass) {
this.loginPass = loginPass;
}
}

Admin.java

@Entity
@Table
// 可选,设置共享主键的名称,默认的主键名称与父类一致。
@PrimaryKeyJoinColumn(name = "userId")
public class Admin extends User {
@Column(name = "role", length = 20, nullable = false)
private String role; public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
}
}

Member.java

@Entity
@Table
// 可选,设置共享主键的名称,默认的主键名称与父类一致。
@PrimaryKeyJoinColumn(name = "userId")
public class Member extends User {
@Column(name = "name", length = 20, nullable = false)
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Test.java

public class Test {
public static void main(String[] params){
// 继承注解:@Inheritance
// 继承策略:InheritanceType.JOINED
// 公共属性公共表,独立属性独立表
new Test().test();
/*
Hibernate:
alter table Admin
drop
foreign key FKjoav33p64suikub3369fpajy4 注:这里可能报一个异常,因为表Admin不存在! Hibernate:
alter table Member
drop
foreign key FKnj6wlxlj0cc3993su1qaykn42 注:这里可能报一个异常,因为表Member不存在! Hibernate:
drop table if exists Admin Hibernate:
drop table if exists Member Hibernate:
drop table if exists User Hibernate:
create table Admin (
role varchar(20) not null,
userId bigint not null,
primary key (userId)
) Hibernate:
create table Member (
name varchar(20) not null,
userId bigint not null,
primary key (userId)
) Hibernate:
create table User (
id bigint not null auto_increment,
loginName varchar(20) not null,
loginPass varchar(20) not null,
primary key (id)
) Hibernate:
alter table User
add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate:
alter table Admin
add constraint FKjoav33p64suikub3369fpajy4
foreign key (userId)
references User (id) Hibernate:
alter table Member
add constraint FKnj6wlxlj0cc3993su1qaykn42
foreign key (userId)
references User (id) Hibernate:
insert
into
User
(loginName, loginPass)
values
(?, ?) Hibernate:
select
last_insert_id() Hibernate:
insert
into
Admin
(role, userId)
values
(?, ?) Hibernate:
select
user0_.id as id1_2_0_,
user0_.loginName as loginNam2_2_0_,
user0_.loginPass as loginPas3_2_0_,
user0_1_.role as role1_0_0_,
user0_2_.name as name1_1_0_,
case
when user0_1_.userId is not null then 1
when user0_2_.userId is not null then 2
when user0_.id is not null then 0
end as clazz_0_
from
User user0_
left outer join
Admin user0_1_
on user0_.id=user0_1_.userId
left outer join
Member user0_2_
on user0_.id=user0_2_.userId
where
user0_.id=? 多态性读取成功:study.t3.Admin@1f9407e Hibernate:
alter table Admin
drop
foreign key FKjoav33p64suikub3369fpajy4 Hibernate:
alter table Member
drop
foreign key FKnj6wlxlj0cc3993su1qaykn42 Hibernate:
drop table if exists Admin Hibernate:
drop table if exists Member Hibernate:
drop table if exists User
*/
} public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass());
SessionFactory factory = null;
try {
factory = (SessionFactory) context.getBean("sessionFactory"); // 多态性添加
boolean success = true;
Session session = null;
Long id = null;
try {
session = factory.openSession();
success = false;
session.beginTransaction();
User user = new Admin();
user.setLoginName("loginName");
user.setLoginPass("loginPass");
((Admin)user).setRole("role");
session.save(user);
session.getTransaction().commit();
id = user.getId();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
} // 多态性读取
if(success){
try {
session = factory.openSession();
session.beginTransaction();
success = false;
User user = session.load(User.class, id);
System.out.println("多态性读取成功:" + user);
session.getTransaction().commit();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
}
}
} finally {
if(factory != null){
factory.close();
factory = null;
}
}
}
}

示例4:继承注解@Inheritance,继承策略InheritanceType.TABLE_PER_CLASS。

User.java

@Entity
@Table
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class User {
//---------------------------------------------------------------
// Field
//--------------------------------------------------------------- @Id
@Column(name = "id")
// 不能使用 GenerationType.IDENTITY,可以使用AUTO,或其它。
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="genId")
@TableGenerator(
name = "genId",
table="GeneratorId",
pkColumnName="genName",
valueColumnName="genValue",
pkColumnValue="nextUserId",
allocationSize=1
)
private Long id; @Column(name = "loginName",
length = 20,
unique = true,
nullable = false,
updatable = false)
private String loginName; @Column(name = "loginPass",
length = 20,
nullable = false)
private String loginPass; //---------------------------------------------------------------
// Method
//--------------------------------------------------------------- public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getLoginName() {
return loginName;
} public void setLoginName(String loginName) {
this.loginName = loginName;
} public String getLoginPass() {
return loginPass;
} public void setLoginPass(String loginPass) {
this.loginPass = loginPass;
}
}

Admin.java

@Entity
@Table
public class Admin extends User {
@Column(name = "role", length = 20, nullable = false)
private String role; public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
}
}

Member.java

@Entity
@Table
public class Member extends User {
@Column(name = "name", length = 20, nullable = false)
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Test.java

public class Test {
public static void main(String[] params){
// 继承注解:@Inheritance
// 继承策略:InheritanceType.TABLE_PER_CLASS
// 公共属性独立表,独立属性独立表
new Test().test();
/*
Hibernate:
drop table if exists Admin Hibernate:
drop table if exists GeneratorId Hibernate:
drop table if exists Member Hibernate:
drop table if exists User Hibernate:
create table Admin (
id bigint not null,
loginName varchar(20) not null,
loginPass varchar(20) not null,
role varchar(20) not null,
primary key (id)
) Hibernate:
create table GeneratorId (
genName varchar(255) not null,
genValue bigint,
primary key (genName)
) Hibernate:
create table Member (
id bigint not null,
loginName varchar(20) not null,
loginPass varchar(20) not null,
name varchar(20) not null,
primary key (id)
) Hibernate:
create table User (
id bigint not null,
loginName varchar(20) not null,
loginPass varchar(20) not null,
primary key (id)
) Hibernate:
alter table Admin
add constraint UK_bdsh7mq6s6xad6ohm08u18uxr unique (loginName) Hibernate:
alter table Member
add constraint UK_jxtse8o1c6l89j39lilw5e2rs unique (loginName) Hibernate:
alter table User
add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate:
select
tbl.genValue
from
GeneratorId tbl
where
tbl.genName=? for update Hibernate:
insert
into
GeneratorId
(genName, genValue)
values
(?,?) Hibernate:
update
GeneratorId
set
genValue=?
where
genValue=?
and genName=? Hibernate:
insert
into
Admin
(loginName, loginPass, role, id)
values
(?, ?, ?, ?) Hibernate:
select
user0_.id as id1_2_0_,
user0_.loginName as loginNam2_2_0_,
user0_.loginPass as loginPas3_2_0_,
user0_.role as role1_0_0_,
user0_.name as name1_1_0_,
user0_.clazz_ as clazz_0_
from
( select
id,
loginName,
loginPass,
null as role,
null as name,
0 as clazz_
from
User
union
select
id,
loginName,
loginPass,
role,
null as name,
1 as clazz_
from
Admin
union
select
id,
loginName,
loginPass,
null as role,
name,
2 as clazz_
from
Member
) user0_
where
user0_.id=? 多态性读取成功:study.t4.Admin@12bf0e2 Hibernate:
drop table if exists Admin Hibernate:
drop table if exists GeneratorId Hibernate:
drop table if exists Member Hibernate:
drop table if exists User
*/
} public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass());
SessionFactory factory = null;
try {
factory = (SessionFactory) context.getBean("sessionFactory"); // 多态性添加
boolean success = true;
Session session = null;
Long id = null;
try {
session = factory.openSession();
success = false;
session.beginTransaction();
User user = new Admin();
user.setLoginName("loginName");
user.setLoginPass("loginPass");
((Admin)user).setRole("role");
session.save(user);
session.getTransaction().commit();
id = user.getId();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
} // 多态性读取
if(success){
try {
session = factory.openSession();
session.beginTransaction();
success = false;
User user = session.load(User.class, id);
System.out.println("多态性读取成功:" + user);
session.getTransaction().commit();
success = true;
} finally {
if(session != null){
if(!success)
session.getTransaction().rollback();
session.close();
session = null;
}
}
}
} finally {
if(factory != null){
factory.close();
factory = null;
}
}
}
}

Hibernate继承注解的更多相关文章

  1. Java、Hibernate(JPA)注解大全

    1.@Entity(name=”EntityName”) 必须,name为可选,对应数据库中一的个表 2.@Table(name=””,catalog=””,schema=””) 可选,通常和@Ent ...

  2. 转Hibernate继承

    hibernate继承映射 以下测试是在mysql中进行的. 1.单表方式 Animal.java @Entity @Inheritance(strategy=InheritanceType.SING ...

  3. hibernate annotation注解方式来处理映射关系

    在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式 ...

  4. 批量产生ssh2项目中hibernate带注解的pojo类的快捷方法

    近几个月一直在忙于项目组的ios应用项目的开发,没有太多时间去研究web应用方面的问题了.刚好,昨天有网友问到如何批量产生hibernate带注解的pojo类的快捷方法,所谓批量就是指将当前数据库中所 ...

  5. Hibernate Annotations 注解

    Hibernate Annotations 注解 对于org.hibernate.annotations与org.hibernate.persistence,它的注释比如Columns,可是不知道怎么 ...

  6. Hibernate中用注解配置一对多双向关联和多对一单向关联

    Hibernate中用注解配置一对多双向关联和多对一单向关联 Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射.在Hibernate3.3之前,需单独下载注解 ...

  7. Hibernate基于注解annotation的配置

    Annotation在框架中是越来越受欢迎了,因为annotation的配置比起XML的配置来说方便了很多,不需要大量的XML来书写,方便简单了很多,只要几个annotation的配置,就可以完成我们 ...

  8. 【JavaEE】Hibernate继承映射,不用多态查询只查父表的方法

    几个月前,我在博问里面发了一个问题:http://q.cnblogs.com/q/64900/,但是一直没有找到好的答案,关闭问题以后才自己解决了,在这里分享一下. 首先我重复一下场景,博问里面举的动 ...

  9. Hibernate基于注解方式配置来实现实体和数据库之间存在某种映射关系

    实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取.在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义. 本文以java注解的形式总结映射关 ...

随机推荐

  1. react diff 极简版

    为什么react这么快呢 ? 因为react用了虚拟DOM: 但是每次虚拟DOM转真实DOM不也是很浪费性能吗 ? nice,所以关键点在Diff算法这里,去对比新旧DOM树,而后通过补丁去更新到真实 ...

  2. CreateRemoteThread简单应用

    要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程 该函数的原型如下: HANDLE CreateRemoteThread(      HAND ...

  3. 命令学习_nslookup

    nslookup 域名 这是最常用最简单的用法,可以直接获得目标域名的IP地址和CNAME. 如下是A记录的返回情况 nslookup命令会采用先反向解释获得使用的DNS服务器的名称,上图中ns.gu ...

  4. CSS 属性1

    CSS列表属性 list-style:列表样式,取值:none.去掉项目符号或编号前面的各种符号. CSS边框属性:每个元素都可以加边框线  border-left:左边框线.   格式:border ...

  5. VMware Workstation 10 配置Ubuntu环境

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 VMware Work ...

  6. Java中9大内置基本数据类型Class实例和数组的Class实例

    1.Java中9大内置几本数据类型: 对于对象来说,可以直接使用对象.getClass()或者Class.forName(className);.类名.class都可以获取Class实例. 但是我们的 ...

  7. 我擦,DELPHI写个浏览器竟然这么容易,我只加了3个控件,写了3句代码。

  8. 使用log4j实现日志API

    添加SLF4J依赖,用于提供日志API, 使用log4j作为实现 1.pom.xml添加SLF4J依赖 <!-- SLF4J --> <dependency> <grou ...

  9. SQL数据表纵横转换

    SELECT DISTINCT '(select b.risk from rhwl_easy_genes_new_risk b where b.genes_id=a.id and b.disease= ...

  10. Python xlwt模块

    Examples Generating Excel Documents Using Python’s xlwt Here are some simple examples using Python’s ...