六、继承映射
Single_Table
1、当多个类存在继承关系的时候,这时候建表的方案有3种。
2、第一种是父类中包含全部的属性,任何子类的信息都由父类对应的数据表来存储。在该表中,增加一个用于表示不同的子类及父类的字段,这样就可以对父类和子类数据进行区分。这种设计成为Single_Table。如下实验:
(1)设计一个父类Person.java。其中定义共有的属性id,name
package com.zgy.hibernate.model;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="discriminator",discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("person")
public class Person {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(2)定义Student.java,定义自己的私有属性score
package com.zgy.hibernate.model;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("student")
public class Student extends Person{
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
(3)定义Teacher.java,定义自己的私有属性title
package com.zgy.hibernate.model;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("teacher")
public class Teacher extends Person{
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
(4)测试save()方法
package com.zgy.hibernate.model;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class ORMapppingTest {
public static SessionFactory sf = null;
@BeforeClass
public static void beforeClass(){
Configuration configure =new Configuration().configure();
new SchemaExport(configure).create(true, true);
sf = configure.buildSessionFactory();
}
@Test
public void testSave() {
Student s = new Student();
s.setName("s1");
s.setScore(80);
Teacher t = new Teacher();
t.setName("t1");
t.setTitle("中级");
Session session = sf.openSession();
session.beginTransaction();
session.save(s);
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClass
public static void afterClass(){
sf.close();
}
}
(5)查看SQL语句:
create table Person (
discriminator varchar(31) not null,
id integer not null auto_increment,
name varchar(255),
score integer,
title varchar(255),
primary key (id)
)
Hibernate: insert into Person (name, score, discriminator) values (?, ?, ‘student‘)
Hibernate: insert into Person (name, title, discriminator) values (?, ?, ‘teacher‘)
可以看出,在Person表中,产生了所有子类的字段,并且在保存数据的时候,每条数据都加入了对应的标识。
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)用于定义存储的策略使用的是单表存储
@DiscriminatorColumn(name="discriminator",discriminatorType=DiscriminatorType.STRING)定义标识列,该列的类型是String类型
@DiscriminatorValue("person")定义Person类的数据在标识列discriminator中的取值是“person”
@DiscriminatorValue("student")定义Student类的数据对应的表示是“student”
@DiscriminatorValue("teacher")定义Teacher类的数据对应的表示是“teacher”
测试读取数据:
@Test
public void testLoad() {
testSave();
Session session = sf.openSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
Person t = (Person)session.load(Person.class, 2);
System.out.println(s.getScore());
System.out.println(t.getName());
session.getTransaction().commit();
session.close();
}
查看SQL语句:
Hibernate: select student0_.id as id2_0_0_, student0_.name as name3_0_0_, student0_.score as score4_0_0_ from Person student0_ where student0_.id=? and student0_.discriminator=‘student‘
80
Hibernate: select person0_.id as id2_0_0_, person0_.name as name3_0_0_, person0_.score as score4_0_0_, person0_.title as title5_0_0_, person0_.discriminator as discrimi1_0_0_ from Person person0_ where person0_.id=?
t1
Table_Per_Class
(1)修改Person.java中的ID生成策略,使用Table生成主键
package com.zgy.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.TableGenerator;
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@TableGenerator(
name="t_gen",
table="t_gen_table",
pkColumnName="t_pk",
valueColumnName="t_value",
pkColumnValue="person_pk",
initialValue=1,
allocationSize=1
)
public class Person {
private int id;
private String name;
@Id
@GeneratedValue(generator="t_gen",strategy=GenerationType.TABLE)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(2)修改Student.java
package com.zgy.hibernate.model;
import javax.persistence.Entity;
@Entity
public class Student extends Person{
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
(3)修改Teacher.java
package com.zgy.hibernate.model;
import javax.persistence.Entity;
@Entity
public class Teacher extends Person{
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
(4)测试save()方法
@Test
public void testSave() {
Student s = new Student();
s.setName("s1");
s.setScore(80);
Teacher t = new Teacher();
t.setName("t1");
t.setTitle("中级");
Session session = sf.openSession();
session.beginTransaction();
session.save(s);
session.save(t);
session.getTransaction().commit();
session.close();
}
(5)观察生成的SQL语句
create table Person (
id integer not null,
name varchar(255),
primary key (id)
)
create table Student (
id integer not null,
name varchar(255),
score integer not null,
primary key (id)
)
create table Teacher (
id integer not null,
name varchar(255),
title varchar(255),
primary key (id)
)
create table t_gen_table (
t_pk varchar(255),
t_value integer
)
Hibernate: insert into Student (name, score, id) values (?, ?, ?)
Hibernate: insert into Teacher (name, title, id) values (?, ?, ?)
(6)测试load()方法
@Test
public void testLoad() {
testSave();
Session session = sf.openSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
Teacher t = (Teacher)session.load(Teacher.class, 2);
System.out.println(s.getScore());
System.out.println(t.getName());
session.getTransaction().commit();
session.close();
}
(7)观察SQL语句
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_, student0_.score as score1_1_0_ from Student student0_ where student0_.id=?
80
Hibernate: select teacher0_.id as id1_0_0_, teacher0_.name as name2_0_0_, teacher0_.title as title1_2_0_ from Teacher teacher0_ where teacher0_.id=?
t1
Joined
(1)修改Person.java
package com.zgy.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(2)Student.java和Teacher只保留@Entity
(3)测试save()方法
@Test
public void testSave() {
Student s = new Student();
s.setName("s1");
s.setScore(80);
Teacher t = new Teacher();
t.setName("t1");
t.setTitle("中级");
Session session = sf.openSession();
session.beginTransaction();
session.save(s);
session.save(t);
session.getTransaction().commit();
session.close();
}
(4)查看SQL语句
create table Person (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table Student (
score integer not null,
id integer not null,
primary key (id)
)
create table Teacher (
title varchar(255),
id integer not null,
primary key (id)
)
alter table Student
add constraint FK_ohs43dct8k52ch2exlmf4bs3l
foreign key (id)
references Person (id)
alter table Teacher
add constraint FK_g6jmt7fcm6gfd0jvhimb9xy84
foreign key (id)
references Person (id)
Hibernate: insert into Person (name) values (?)
Hibernate: insert into Student (score, id) values (?, ?)
Hibernate: insert into Person (name) values (?)
Hibernate: insert into Teacher (title, id) values (?, ?)
(5)测试load()方法
@Test
public void testLoad() {
testSave();
Session session = sf.openSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
Teacher t = (Teacher)session.load(Teacher.class, 2);
System.out.println(s.getScore());
System.out.println(t.getName());
session.getTransaction().commit();
session.close();
}
(6)观察SQL语句
Hibernate: select student0_.id as id1_0_0_, student0_1_.name as name2_0_0_, student0_.score as score1_1_0_ from Student student0_ inner join Person student0_1_ on student0_.id=student0_1_.id where student0_.id=?
80
Hibernate: select teacher0_.id as id1_0_0_, teacher0_1_.name as name2_0_0_, teacher0_.title as title1_2_0_ from Teacher teacher0_ inner join Person teacher0_1_ on teacher0_.id=teacher0_1_.id where teacher0_.id=?