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. h5判断是否为iphonex

    js移动端页面判断是否是iphoneX 转自https://blog.csdn.net/weixin_39924326/article/details/80352929 function isIPho ...

  2. 框架前期准备篇之AutoFac常见用法总结 转载

    框架前期准备篇之AutoFac常见用法总结 一. 说在前面的话 凡是大约工作在两年以上的朋友们,或多或少都会接触到一些框架搭建方面的知识,只要一谈到框架搭建这个问题或者最佳用法这个问题,势必会引起一点 ...

  3. C语言进阶学习第一章

    1.在C语言里面使用scanf给某个变量赋值时候,如果成功返回1,失败返回0:测试代码如下: /***假如在键盘输入的不是整形数据,则输出0,否则输出1***/ void main() { int a ...

  4. PAT甲级——A1112 Stucked Keyboard【20】

    On a broken keyboard, some of the keys are always stucked. So when you type some sentences, the char ...

  5. maven配置步骤

    仅做操作手册使用,一些操作频率较高的步骤已省略 第一步:度娘下载maven并解压 此处使用了apache-maven-3.2.5-bin.zip, 解压后复制到了D盘的D:\maven\apache- ...

  6. iOS开发系列-NSURLConnection

    概述 NSURLConnection是负责发送请求,建立客户端与服务端的连接.发送数据给服务器,并收集来自服务器的响应数据.其中NSURLRequest类是用来封装一个请求,包含NSURL对象.请求方 ...

  7. 转载别人的ftp,觉得目录结构不错,学习

    开发简单的FTP:1. 用户登陆2. 上传/下载文件3. 不同用户家目录不同4. 查看当前目录下文件5. 充分使用面向对象知识 REDMAE 1 用户登陆 2 3 1.查看用户目录文件 4 2.上传文 ...

  8. 容斥原理——hdu1796

    /* 遇到这种题一般用dfs,枚举起点来做 但是本题如何进行容斥? 比如以x为起点,第一步dfs到y,那么因子有lcm(x,y)的 所有数要被减掉(容斥中偶数是减法) 然后第二步dfs到z,那么因子有 ...

  9. 容斥原理——hdu3208

    和hdu2204有点像 这题要特别注意精度问题,如pow的精度需要自己搞一下,然后最大的longlong可以设为1<<31 /* 只要求[1,n]范围内的sum即可 那么先枚举幂次k[1, ...

  10. springboot指定项目访问路径前缀

    springboot默认的运行方式是没有项目前缀的 如果这时候我们要加上调试或者发布,可以使用下面的方法加上 方法: