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;
}
}
}
}

最新文章

  1. JavaEE开发基础
  2. linux重启mysql无法启动
  3. grub2添加win引导(未试用)
  4. less
  5. 都别说工资低了,我们来一起写简单的dom选择器吧!
  6. 使用redis进行消息推送
  7. BZOJ 2466: [中山市选2009]树
  8. F.I.S本地环境的搭建教程
  9. Leveldb Advanced
  10. 20141031--SQL分组,数学函数,聚合函数
  11. (原)anaconda 的安装与在pycharm中的版本切换
  12. 用js使得输入框input只能输入数字
  13. 《剑指offer》和为S的连续正数序列
  14. sql语句应用
  15. Centos 7创建一个服务
  16. iOS开发之一句代码检测APP版本的更新
  17. LINQ分组取出第一条数据
  18. OpenGL——折线图柱状图饼图绘制
  19. JavaScript中通过arguments对象实现对象的重载
  20. SMACH专题(三)----几种State类型

热门文章

  1. System.IO.Directory.cs
  2. JAVA 设计模式之 原型模式详解
  3. python编码(31-01)
  4. 《初识Python之认识常量type函数》
  5. 面试系列 31 zk都有哪些使用场景
  6. object_detection/protos/*.proto: No such file or directory
  7. 现代软件工程HW1:词频统计
  8. 转载别人的ftp,觉得目录结构不错,学习
  9. ActiveMQ 基础
  10. ng-zorro-mobile中遇到的问题