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. 2018-2019-2 20175323 实验一《Java开发环境的熟悉》实验报告

    java开发环境的熟悉-1 java开发环境的熟悉-2 下载IDEA和破解的过程我参考了https://blog.csdn.net/shengshengshiwo/article/details/79 ...

  2. iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)

    1.前言 开发时常常用数组对数据进行处理,对NSMutableArray进行操作时经常导致程序崩溃,特研究一下NSArray的类簇!涉及__NSPlaceholderArray.__NSArray0. ...

  3. Mybatis功能架构及执行流程

    原文地址:http://blog.51cto.com/12222886/2052647 一.功能架构设计 功能架构讲解: 我们把Mybatis的功能架构分为三层: (1) API接口层:提供给外部使用 ...

  4. 小tips: zoom和transform:scale的区别

    小tips: zoom和transform:scale的区别 转自 张鑫旭 前端大神 by zhangxinxu from http://www.zhangxinxu.com本文地址:http://w ...

  5. springboot-配置多数据源之番外篇(分包实现)

    场景: 随着业务发展,系统连接多数据库成为常态,继前面AOP的实现方式之后,这里记录一下分包实现的方式. 实现:  1.pom.xml <?xml version="1.0" ...

  6. READING | 我是一只IT小小鸟

    “世界是如此的熙熙攘攘,让年轻的心找不到方向,但这些人是不能小看的啊,如果他们开始敲打自己的命令行.” “知之者不如好知者,好之者不如乐之者”,很多IT界的优秀人才都对计算机技术或者IT技术有着浓厚的 ...

  7. JAVA数据结构之数组

    接下来的几篇博文会在最近仔细研读数据结构与算法的书籍后会摘录一些要点和总结一些自己的心得体会,帮助大家更深入地理解java中的数据结构和一些基本的算法,同时巩固自己数据结构和算法这些最基础的计算机知识 ...

  8. js怎样截取字符串后几位以及截取字符串前几位

    想要截取字符串前几位与后几位,主要代码如下 截取字符串前几位 var disName ='开心一族漂亮家园'; var shortName = disName.substring(0,5); cons ...

  9. Eureka服务治理学习笔记(摘抄)

    1.简介 EureKa在Spring Cloud全家桶中担任着服务的注册与发现的落地实现.Netflix在设计EureKa时遵循着AP原则,它基于R EST的服务,用于定位服务,以实现云端中间层服务发 ...

  10. Redis学习目录

    目录   持续更新... Redis简介 Redis安装及基本配置 Redis持久化 Redis开发及管理实战 Redis高可用及集群 Redis多API开发