Hibernate第三课--级联关系,关联关系,集合和继承映射

来源:互联网 发布:数据统计问题有哪些 编辑:程序博客网 时间:2024/05/28 15:06
级联关系
关联关系
集合关系
继承关系
Node树形节点

级联关系
1. CascadeType.PERSIST:级联新增(又称级联保存):对order对象保存时也对items里的对象也会保存。对应EntityManager的presist方法
 例子:只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)
 
2. CascadeType.MERGE:级联合并(级联更新):若items属性修改了那么order对象保存时同时修改items里的对象。对应EntityManager的merge方法  
例子:指A类新增或者变化,会级联B对象(新增或者变化)

3. CascadeType.REMOVE:级联删除:对order对象删除也对items里的对象也会删除。对应EntityManager的remove方法 
例子:REMOVE只有A类删除时,会级联删除B类;

4. CascadeType.REFRESH:级联刷新:获取order对象里也同时也重新获取最新的items时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据   (用的比较少)

5. CascadeType.ALL:以上四种都是
综上所述:一般的,用CascadeType.MERGE:级联合并(级联更新)就能达到级更新同时又稳定不报错。


一 Hibernate关联关系
@JoinColumn:在a主表外键name=“b_id”(不写name默认是b_id)连接从表b的id

关联关系数据库表主类持久类测试类说明一对一单向主键
CREATE TABLE `husband` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `wife` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue
public int getId()
@OneToOne
@PrimaryKeyJoinColumn
public Wife getWife()

private int id;
private String name;
@Id
@GeneratedValue
public int getId()

Husband h = new Husband(); Wife w = new Wife();
w.setName("sangwu");
h.setName("zhangsan"); 
h.setWife(w);
session.save(w); 
session.save(h);

一个丈夫只有一个妻子一对一双向主键同一对一单向主键同一对一单向主键
private int id;
private String name;
private Husband husband;
@OneToOne
@PrimaryKeyJoinColumn
public Husband getHusband()
@Id
@GeneratedValue
public int getId()
比一对一单向主键多:
Husband字段
@OneToOne
@PrimaryKeyJoinColumn
Husband h = new Husband();
Wife w = new Wife();
w.setName("sangwu");
h.setName("zhangsan");
h.setWife(w);
w.setHusband(h);
session.save(w);
session.save(h);

一个丈夫只有一个妻子一对一单向外键
CREATE TABLE `husband` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`wifeId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_kruq9jfxa0jrc2od8dbh09mia` (`wifeId`),
CONSTRAINT `FK_kruq9jfxa0jrc2od8dbh09mia` FOREIGN KEY (`wifeId`) REFERENCES `wife` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `wife` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue
public int getId()
@OneToOne
@JoinColumn(name="wifeId") //不写name 默认是生成wife_id
public Wife getWife()

private int id;
private String name;
@Id
@GeneratedValue
public int getId()

Husband h = new Husband(); 
Wife w = new Wife();
w.setName("sangwu"); 
h.setName("zhangsan");
h.setWife(w);
session.save(w); 
session.save(h);

一个丈夫只有一个妻子一对一双向外键同一对一单向主键同一对一单向主键
private int id;
private String name;
private Husband husband;
 
@OneToOne(mappedBy="wife")
public Husband getHusband()
 
@Id
@GeneratedValue
public int getId()
比一对一单向主键多:
Husband字段
@OneToOne(mappedBy="wife")
Husband h = new Husband(); 
Wife w = new Wife();
w.setName("sangwu"); 
h.setName("zhangsan");
h.setWife(w); 
w.setHusband(h);
session.save(w); 
session.save(h);

一个丈夫只有一个妻子单向多对一
CREATE TABLE `t_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`group_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_e5f24mh6aryt9hsy99oydps6g` (`group_id`),
CONSTRAINT `FK_e5f24mh6aryt9hsy99oydps6g` FOREIGN KEY (`group_id`) REFERENCES `t_group` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

//User类
private int id;
private String name;
private Group group;
@ManyToOne
@JoinColumn
public Group getGroup() {
return group;
}


//Group类
private int id;
private String name;
@Id
@GeneratedValue
public int getId()

Group g = new Group();
User u1 =new User(); 
User u2 =new User();
u1.setName("u1"); 
u2.setName("u2");
g.setName("group");
u1.setGroup(g); 
u2.setGroup(g);
session.save(g); 
session.save(u1); 
session.save(u2);

多个用户在一个组单向一对多同多对一单向
//Group类
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@Id
@GeneratedValue
public int getId()
@OneToMany
@JoinColumn(name="group_id")
public Set<User> getUsers()
JoinColumn实际是上在主的一方,外键连接从的表,但是在一对多时,需要JoinColumn在从表中标识,实际上还是在主表外键连接从表的作用
//User类
private int id;
private String name;
@Id
@GeneratedValue
public int getId()

Group g = new Group();
User u1 =new User(); 
User u2 =new User();
u1.setName("u1"); 
u2.setName("u2");
g.setName("group1");
g.getUsers().add(u1); 
g.getUsers().add(u2);
session.save(u1); 
session.save(u2); 
session.save(g);

一个组有多个用户双向一对多等于多对一同多对一单向
//User
private int id;
private String name;
private Group group;
@ManyToOne
@JoinColumn(name='group_id') //加或者不加都可以
public Group getGroup()
@Id
@GeneratedValue
public int getId()

//Group
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@Id
@GeneratedValue
public int getId()
@OneToMany(mappedBy="group")
public Set<User> getUsers()

Group g = new Group();
User u1 =new User(); 
User u2 =new User();
u1.setName("u1"); 
u2.setName("u2");
g.setName("group1");
g.getUsers().add(u1); 
g.getUsers().add(u2);
u1.setGroup(g); 
u2.setGroup(g);
session.save(u1); 
session.save(u2); 
session.save(g);

一个组有多个用户单向多对多
 
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `t_s` (
`teacher_id` int(11) NOT NULL,
`student_id` int(11) NOT NULL,
PRIMARY KEY (`teacher_id`,`student_id`),
KEY `FK_3no0wm9bwtogr87t4gvd4t3x5` (`student_id`),
CONSTRAINT `FK_3no0wm9bwtogr87t4gvd4t3x5` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`),
CONSTRAINT `FK_pj2fmd6skwfi7jm2avlo4n6mf` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

//Teacher
private int id;
private String name;
private Set<Student> students = new HashSet<Student>();
@Id
@GeneratedValue
public int getId()
@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},
inverseJoinColumns={@JoinColumn(name="student_id")}
)
public Set<Student> getStudents()

//User类
private int id;
private String name;
@Id
@GeneratedValue
public int getId()

Student s1 = new Student(); 
s1.setName("s1");
Student s2 = new Student(); 
s2.setName("s2");
Student s3 = new Student(); 
s3.setName("s3");
Teacher t1 = new Teacher(); 
t1.setName("t1");
Teacher t2 = new Teacher(); 
t2.setName("t2");
Teacher t3 = new Teacher(); 
t3.setName("t3");
t1.getStudents().add(s2); 
t1.getStudents().add(s3);
t2.getStudents().add(s1); 
t2.getStudents().add(s3);
t3.getStudents().add(s1); 
t3.getStudents().add(s2);
session.save(s1); 
session.save(s2); 
session.save(s3); 
session.save(t1);
session.save(t2); 
session.save(t3);

一个学生有多个老师,一个老师教多个学生双向多对多同单向多对多同单向多对多
private int id;
private String name;
private Set<Teacher> teachers = new HashSet<Teacher>();
@ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers()
@Id
@GeneratedValue
public int getId()
比一对一单向主键多:
Set<Teacher> teachers字段
@OneToOne(mappedBy="wife")
Student s1 = new Student();
s1.setName("s1");
 
Student s2 = new Student();
s2.setName("s2");
 
Student s3 = new Student();
s3.setName("s3");
 
Teacher t1 = new Teacher();
t1.setName("t1");
 
Teacher t2 = new Teacher();
t2.setName("t2");
 
Teacher t3 = new Teacher();
t3.setName("t3");
 
t1.getStudents().add(s2);
t1.getStudents().add(s3);
 
t2.getStudents().add(s1);
t2.getStudents().add(s3);
 
t3.getStudents().add(s1);
t3.getStudents().add(s2);
 
session.save(s1);
session.save(s2);
session.save(s3);
session.save(t1);
session.save(t2);
session.save(t3);

一个学生有多个老师,一个老师教多个学生组件映射
CREATE TABLE `t_employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`zipCode` varchar(255) DEFAULT NULL,
`contactTel` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`zipCode` varchar(255) DEFAULT NULL,
`contactTel` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

//Employee
private int id;
private String name;
private Contact contact;
@Id
@GeneratedValue
public int getId()
@Embedded
public Contact getContact()
//User
private int id;
private String name;
private Contact contact;
@Id
@GeneratedValue
public int getId()
@Embedded
public Contact getContact()

public class Contact {
 
private String email;
private String address;
private String zipCode;
private String contactTel;
/*省略
set...方法
get...方法
*/
}

Employee e = new Employee();
User u = new User();
 
e.setContact(new Contact("email_e","address_e","zipCode_e","contactTel_e"));
u.setContact(new Contact("email_u","address_u","zipCode_u","contactTel_u"));
e.setName("employee");
u.setName("User");
 
session.save(e);
session.save(u);

一个类的属性是另一个类,或者两个类有相同字段,抽象出一个实体独享类      


 复合主键
多个字段构成唯一性
复合主键的映射:一般情况把主键相关的属性抽取出来单独放入一个类中。
必须实现序列化接口:重写hashCode(),equals()
数据库表
CREATE TABLE `comprimary` (
`p_id` int(11) NOT NULL,
`p_date` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`p_id`,`p_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

复合主键类需要实现Serializable的hashCode(),equals()方法
复合主键类方法复合主键类实体类测试将主键类注解为@Embeddable,并将主键的属性注解为@Id
 
 
 
 
@Embeddable
public class ComprimaryPK1 implements Serializable
 
private int p_id;
private int p_date;
 
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + p_date;
result = prime * result + p_id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ComprimaryPK1 other = (ComprimaryPK1) obj;
if (p_date != other.p_date)
return false;
if (p_id != other.p_id)
return false;
return true;
}

@Entity(name="comprimary")
public class Comprimary1 {
private ComprimaryPK1 comprimary;
private String name;
 
@Id
public ComprimaryPK1 getComprimary()

 将组件的属性注解为@EmbeddedId
复合主键类不需要任何注解复合主键类不需要任何注解
@Entity(name="comprimary")
public class Comprimary2 {
private ComprimaryPK2_3 comprimary;
private String name;
//复合主键
@EmbeddedId
public ComprimaryPK2_3 getComprimary()

Comprimary2 p = new Comprimary2();
p.setComprimary(new ComprimaryPK2_3(2, 2));
p.setName("zhangsan");
session.save(p);

在实体类添加注解@IdClass,并将该实体中所有属于复合主键类的属性都注解为@Id复合主键类不需要任何注解
@Entity(name="comprimary")
@IdClass(ComprimaryPK2_3.class)//引用复合主键类
public class Comprimary3 {
//加入复合主键类的属性
private int p_id;
//加入复合主键类的属性
private int p_date;
private String name;
@Id
public int getP_id() {
return p_id;
}
@Id
public int getP_date() {
return p_date;
}

Comprimary3 p = new Comprimary3();
p.setP_id(3);
p.setP_date(3);
p.setName("zhangsan");
session.save(p);



二. 集合映射(com.liuhao.hibernate4.demo.set_list_map)
数据库表结构都是一样的
使用的是双向多对一关系
CREATE TABLE `t_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
 
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`group_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_e5f24mh6aryt9hsy99oydps6g` (`group_id`),
CONSTRAINT `FK_e5f24mh6aryt9hsy99oydps6g` FOREIGN KEY (`group_id`) REFERENCES `t_group` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;


集合类型一的一端多的一端测试Set
private int id;
private String name;
private Set<SetUser> user = new HashSet<SetUser>();
// Set 集合
@OneToMany(mappedBy = "group")
public Set<SetUser> getUser() {
return user;
}
public void setUser(Set<SetUser> user) {
this.user = user;
}
@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;
}

private int id;
private String name;
private SetGroup group;
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToOne
public SetGroup getGroup() {
return group;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setGroup(SetGroup group) {
this.group = group;
}

session.beginTransaction();
 
SetUser u1 = new SetUser();
u1.setName("u1");
 
SetUser u2 = new SetUser();
u2.setName("u2");
 
SetUser u3 = new SetUser();
u3.setName("u3");
 
SetUser u4 = new SetUser();
u4.setName("u4");
 
SetGroup g1 = new SetGroup();
g1.setName("g1");
g1.getUser().add(u1);
g1.getUser().add(u2);
 
SetGroup g2 = new SetGroup();
g2.setName("g2");
g2.getUser().add(u3);
g2.getUser().add(u4);
 
u1.setGroup(g1);
u2.setGroup(g1);
u3.setGroup(g2);
u4.setGroup(g2);
 
session.save(g1);
session.save(g2);
session.save(u1);
session.save(u2);
session.save(u3);
session.save(u4);
 
session.flush();
session.getTransaction().commit();

ListList和Set没有区别将Set改成List
private int id;
private String name;
// List 集合
private List<ListUser> user = new ArrayList<ListUser>();
 
@OneToMany(mappedBy = "group")
public List<ListUser> getUser() {
return user;
}
public void setUser(List<ListUser> user) {
this.user = user;
}
@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;
}

private int id;
private String name;
private ListGroup group;
 
@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;
}
@ManyToOne
public ListGroup getGroup() {
return group;
}
public void setGroup(ListGroup group) {
this.group = group;
}

@Test
public void testList() {
session.beginTransaction();
ListUser u1 = new ListUser();
u1.setName("u1");
ListUser u2 = new ListUser();
u2.setName("u2");
ListUser u3 = new ListUser();
u3.setName("u3");
ListUser u4 = new ListUser();
u4.setName("u4");
ListGroup g1 = new ListGroup();
g1.setName("g1");
g1.getUser().add(u1);
g1.getUser().add(u2);
ListGroup g2 = new ListGroup();
g2.setName("g2");
g2.getUser().add(u3);
g2.getUser().add(u4);
u1.setGroup(g1);
u2.setGroup(g1);
u3.setGroup(g2);
u4.setGroup(g2);
session.save(g1);
session.save(g2);
session.save(u1);
session.save(u2);
session.save(u3);
session.save(u4);
session.flush();
session.getTransaction().commit();
}

MapMap是将Set改成Map,同时添加一个@Mapkey(value="id")指定map中key对应字段
private int id;
private String name;
// Map 集合
private Map<Integer, MapUser> user = new HashMap<Integer, MapUser>();
 
@OneToMany(mappedBy = "group")
@MapKey(name = "id")//注解key的字段
public Map<Integer, MapUser> getUser() {
return user;
}
public void setUser(Map<Integer, MapUser> user) {
this.user = user;
}
@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;
}

private int id;
private String name;
private MapGroup group;
 
@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;
}
@ManyToOne
public MapGroup getGroup() {
return group;
}
public void setGroup(MapGroup group) {
this.group = group;
}

 
@Test
public void testMap() {
session.beginTransaction();
MapUser u1 = new MapUser();
u1.setName("u1");
MapUser u2 = new MapUser();
u2.setName("u2");
MapUser u3 = new MapUser();
u3.setName("u3");
MapUser u4 = new MapUser();
u4.setName("u4");
MapGroup g1 = new MapGroup();
g1.setName("g1");
g1.getUser().put(u1.getId(), u1);
g1.getUser().put(u2.getId(), u2);
MapGroup g2 = new MapGroup();
g2.setName("g2");
g2.getUser().put(u3.getId(), u3);
g2.getUser().put(u4.getId(), u4);
u1.setGroup(g1);
u2.setGroup(g1);
u3.setGroup(g2);
u4.setGroup(g2);
session.save(g1);
session.save(g2);
session.save(u1);
session.save(u2);
session.save(u3);
session.save(u4);
session.flush();
session.getTransaction().commit();
}



三. 继承映射(com.liuhao.hibernate4.demo.inherit)

继承映射:就是把类的继承关系映射到数据库里(首先正确的存储,再正确的加载数据)
(一) 继承关联映射的分类:
1. 单表继承:每棵类继承树使用一个表(table per class hierarchy)
2. 具体表继承:每个子类一个表(table per subclass)
3. 类表继承:每个具体类一个表(table per concrete class)(有一些限制)

 实例环境:动物Animal有三个基本属性,然后有一个Pig继承了它并扩展了一个属性,还有一个Brid也继承了并且扩展了一个属性
对象模型:


(二) 单表继承SINGLE_TABLE:
每棵类继承树使用同一个表
把所有的属性都要存储表中,目前至少需要5个字段,另外需要加入一个标识字段(表示哪个具体的子类)
animal

①、id:表主键
②、name:动物的姓名,所有的动物都有
③、sex:动物的性别,所有的动物都有
④、weight:猪(Pig)的重量,只有猪才有,所以鸟就没有重量数据
⑤、height:鸟(height)的调试,只有鸟才有,所以猪猪就没有高度数据
⑥、type:表示动物的类型;P表示猪;B表示鸟

注解实体类:
父类:
//@Inheritance 表示继承关系   SINGLE.TABLE单表继承
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
//DiscriminatorColumn 区别的字段和类型(用于数据库表创建)
@DiscriminatorColumn(name="type",
discriminatorType=DiscriminatorType.STRING)
//DiscriminatorValue 当前类使用的区别标示值
@DiscriminatorValue(value = "animal")

Animal
package com.liuhao.hibernate4.demo.inherit.singletable;
 
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;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",
discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value = "animal")
public class Animal {
private int id;
private String name;
private boolean sex;
public Animal(){};
public Animal(int id, String name, boolean sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
@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;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("id", id);
builder.append("name", name);
builder.append("sex", sex);
return builder.toString();
}
}

子类:
只需要
//DiscriminatorValue 子类使用的区别标示值
@DiscriminatorValue(value = "xxx")

Pig
package com.liuhao.hibernate4.demo.inherit.singletable;
 
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import org.apache.commons.lang3.builder.ToStringBuilder;
 
@Entity
@DiscriminatorValue(value = "pig")
public class Pig extends Animal {
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("weight", weight);
return builder.toString();
}
}
Bird
package com.liuhao.hibernate4.demo.inherit.singletable;
 
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import org.apache.commons.lang3.builder.ToStringBuilder;
 
@Entity
@DiscriminatorValue(value = "bird")
public class Bird extends Animal {
private int height;
 
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("height", height);
return builder.toString();
}
}

导出数据库表:
CREATE TABLE `animal` (
`type` varchar(31) NOT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`weight` int(11) DEFAULT NULL,
`height` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


测试类:
1. 插入父类,子类数据
 
/**
* singtable 单表继承
*/
@Test
public void testSingTable() {
session.beginTransaction();
 
Animal al = new Animal();
 
al.setName("al1");
al.setSex(true);
 
Pig p1 = new Pig();
p1.setName("p1");
p1.setSex(true);
p1.setWeight(200);
 
Bird b1 = new Bird();
b1.setName("b1");
b1.setSex(false);
b1.setHeight(30);
 
session.saveOrUpdate(al);
session.saveOrUpdate(p1);
session.saveOrUpdate(b1);
 
log.debug("Animal " + al);
log.debug("Pig extends Animal" + p1);
log.debug("Bird extends Animal" + b1);
 
session.flush();
session.getTransaction().commit();
}
控制台输出:
Hibernate:
insert
into
Animal
(name, sex, type)
values
(?, ?, 'animal')        //type被标识为 animal , 没有height , weight
Hibernate:
insert
into
Animal
(name, sex, weight, type)
values
(?, ?, ?, 'pig')        //type被标识为 pig , 没有weight
Hibernate:
insert
into
Animal
(name, sex, height, type)
values
(?, ?, ?, 'bird')        //type被标识为 bird , 没有height
2015-07-02 10:06:19,725 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Animal@61cd2[id=1,name=al1,sex=true]
2015-07-02 10:06:19,725 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Pig extends Animalcom.liuhao.hibernate4.demo.inherit.singletable.Pig@1469658[weight=200]
2015-07-02 10:06:19,725 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Bird extends Animalcom.liuhao.hibernate4.demo.inherit.singletable.Bird@1dafb4e[height=30]

执行后:



2. 加载父类
 
/**
* singtable 单表继承 加载父类
*/
@Test
public void testSuper() {
session.beginTransaction();
Animal al = (Animal) session.load(Animal.class, 1);
log.debug("Animal " + al);
session.flush();
session.getTransaction().commit();
}
控制台输出:
Hibernate:
select
animal0_.id as id2_0_0_,
animal0_.name as name3_0_0_,
animal0_.sex as sex4_0_0_,
animal0_.weight as weight5_0_0_,
animal0_.height as height6_0_0_,
animal0_.type as type1_0_0_
from
Animal animal0_
where
animal0_.id=?
//注:因为使用父类加载数据,所以hibernate会将所有字段(height、weight、type)的数据全部加载,并且条件中没有识别字段type(也就不区分什么子类,把所有子类全部加载上来?。)
2015-07-02 10:10:41,843 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Animal@1c8b24d[id=1,name=al1,sex=true]


3. 加载子类
package com.liuhao.hibernate4.demo.uril;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
 
public class HibernateUtil {
private static final SessionFactory sessionFactory = createSessionFactory();
 
private HibernateUtil() {
}
 
private static SessionFactory createSessionFactory() {
SessionFactory sf = null;
try {
 
Configuration cfg = new Configuration();
cfg.configure(); // 重要,表示执行默认的hibernate.cfg.xml配置文件
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(
cfg.getProperties()).buildServiceRegistry();
 
sf = cfg.buildSessionFactory(sr);
 
} catch (Exception e) {
e.printStackTrace();
}
return sf;
}
 
public synchronized static SessionFactory getSessionFactory() {
return sessionFactory;
}
 
}

控制台输出:
Hibernate:
select
pig0_.id as id2_0_0_,
pig0_.name as name3_0_0_,
pig0_.sex as sex4_0_0_,
pig0_.weight as weight5_0_0_
from
Animal pig0_
where
pig0_.id=?
and pig0_.type='pig'
// type = 'pig'自动确定类型,且只加载子类的字段
2015-07-02 10:13:02,691 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Pig com.liuhao.hibernate4.demo.inherit.singletable.Pig@1de4dd8[weight=200]
Hibernate:
select
bird0_.id as id2_0_0_,
bird0_.name as name3_0_0_,
bird0_.sex as sex4_0_0_,
bird0_.height as height6_0_0_
from
Animal bird0_
where
bird0_.id=?
and bird0_.type='bird'
// type = 'bird'自动确定类型,且只加载子类的字段
2015-07-02 10:13:02,756 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Bird com.liuhao.hibernate4.demo.inherit.singletable.Bird@15c97e4[height=30]

4. 多态查询
4.1 load方法
load是延迟加载,返回代理对象
select查询受load入参类型影响
返回的持久化实例
不受数据库查询主键标识得到行type类型影响,
受load入参类型影响
解决办法:
lazy=false 修改成非延迟加载

 
/**
* singtable 单表继承
* 多态查询 load不支持多态查询,
* 因为load延迟加载不支持多态查询返回的是load(Object.class,id)的Object代理对象
* 数据库 id=2 是一个type='pig'对象
*
-------------------------------------
load(Animal.class, 2) -->返回Animal
输出结果: 没有对字段区分
是动物
Hibernate:
select
animal0_.id as id2_0_0_,
animal0_.name as name3_0_0_,
animal0_.sex as sex4_0_0_,
animal0_.weight as weight5_0_0_,
animal0_.height as height6_0_0_,
animal0_.type as type1_0_0_
from
Animal animal0_
where
animal0_.id=?
2015-07-02 10:40:06,100 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Pig@1de4dd8[weight=200]
 
-------------------------------------
load(Pig.class, 2) -->返回Pig
 
输出结果:对字段区分
是猪
Hibernate:
select
pig0_.id as id2_0_0_,
pig0_.name as name3_0_0_,
pig0_.sex as sex4_0_0_,
pig0_.weight as weight5_0_0_
from
Animal pig0_
where
pig0_.id=?
and pig0_.type='pig'
2015-07-02 10:32:03,744 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Pig@1de4dd8[weight=200]
-------------------------------------
-------------------------------------
load(Bird.class, 2) -->返回Bird
输出结果:报错字段不匹配插入不进去
是鸟
Hibernate:
select
bird0_.id as id2_0_0_,
bird0_.name as name3_0_0_,
bird0_.sex as sex4_0_0_,
bird0_.height as height6_0_0_
from
Animal bird0_
where
bird0_.id=?
and bird0_.type='bird'
* 结论:
* load是延迟加载
*select查询受load入参类型影响
*返回的持久化实例
*不受数据库查询主键标识得到行type类型影响,
*受load入参类型影响
*解决办法:
*lazy=false 修改成非延迟加载
*/
@Test
public void testMulti_load() {
session.beginTransaction();
// id=2 是一个pig 因为lazy=true(false支持多态查询) load不支持多态查询 所以返回的是一个Animal的子类
Animal al = (Animal) session.load(Animal.class, 2);
//Animal al = (Animal) session.load(Pig.class, 2);
//Animal al = (Animal) session.load(Bird.class, 2);
 
if (al instanceof Pig) {
System.out.println("是猪");
} else if(al instanceof Bird){
System.out.println("是鸟");
} else if(al instanceof Animal){
System.out.println("是动物");
} else{
System.out.println("是未知生物");
}
 
log.debug("Animal " + al);
 
session.flush();
session.getTransaction().commit();
 
}



4.2 get方法
get方法select查询受get入参影响,
但是返回持久化实例受数据库查询主键标识得到行type类型影响
 
/**
* singtable 单表继承
* 多态查询 
* get 支持多态查询
* 数据库 id=2 是一个type='pig'对象
* get是直接加载
*
* ---------------------------------------------
* 即使get(Animal.class, 2) 返回的也是一个Pig对象
*
* 控制台输出: 返回结果正确,查询条件没有区分type
* Hibernate:
select
animal0_.id as id2_0_0_,
animal0_.name as name3_0_0_,
animal0_.sex as sex4_0_0_,
animal0_.weight as weight5_0_0_,
animal0_.height as height6_0_0_,
animal0_.type as type1_0_0_
from
Animal animal0_
where
animal0_.id=?
是猪
2015-07-02 10:44:42,273 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Pig@1de4dd8[weight=200]
---------------------------------------------
get(Pig.class, 2) 返回的也是一个Pig对象
控制台输出: type有区分,返回结果也正确
Hibernate:
select
pig0_.id as id2_0_0_,
pig0_.name as name3_0_0_,
pig0_.sex as sex4_0_0_,
pig0_.weight as weight5_0_0_
from
Animal pig0_
where
pig0_.id=?
and pig0_.type='pig'
是猪
2015-07-02 10:48:35,202 [com.liuhao.hibernate4.demo.inherit.test.InheritTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.singletable.Pig@156b386[weight=200]
*
* 总结:
* get方法select查询受get入参影响,
* 但是返回持久化实例受数据库查询主键标识得到行type类型影响
*/
@Test
public void testMulti_get() {
session.beginTransaction();
 
//Animal al = (Animal) session.get(Animal.class, 2);
Animal al = (Animal) session.get(Pig.class, 2);
 
if (al instanceof Pig) {
System.out.println("是猪");
} else if(al instanceof Bird){
System.out.println("是鸟");
} else if(al instanceof Animal){
System.out.println("是动物");
} else{
System.out.println("是未知生物");
}
 
log.debug("Animal " + al);
 
session.flush();
session.getTransaction().commit();
}

4.3 HQL查询
 
/**
* singtable 单表继承 HQL支持多态查询
*/
@Test
public void testMulti_HQL() {
System.out.println("========================");
session.beginTransaction();
// HQL支持多态查询
List list = session.createQuery("from Animal").list();
for (Iterator it = list.iterator(); it.hasNext();) {
Animal al = (Animal) it.next();
if (al instanceof Pig) {
System.out.println("是猪");
} else if(al instanceof Bird){
System.out.println("是鸟");
} else if(al instanceof Animal){
System.out.println("是动物");
} else{
System.out.println("是未知生物");
}
log.debug("Animal " + al);
}
 
session.flush();
session.getTransaction().commit();
System.out.println("========================");
}

4.4 HQL查询hibernate.cfg.xml映射所有表
/**
* singtable 单表继承
* HQL查询所有表中所有的实体对象
*/
@Test
public void testMulti_HQLALL() {
System.out.println("========================");
session.beginTransaction();
// HQL支持多态查询
List list = session.createQuery("from java.lang.Object").list();
for (Iterator it = list.iterator(); it.hasNext();) {
Object obj = it.next();
if (obj instanceof Pig) {
System.out.println("是猪");
} else if(obj instanceof Bird){
System.out.println("是鸟");
} else if(obj instanceof Animal){
System.out.println("是动物");
} else{
System.out.println("是未知生物");
}
log.debug("Object " + obj);
}
session.flush();
session.getTransaction().commit();
System.out.println("========================");
}

(三) 具体表继承JOINED(com.liuhao.hibernate4.demo.inherit.joined):
每个类映射成一个表(table per subclass)
对象模型不用变化,存储模型需要变化


关系模型:
每个类映射成一个表(table per subclass)

注:因为需要每个类都映射成一张表,所以Animal也映射成一张表(animal),表中字段为实体类属性
而pig子类也需要映射成一张表(pid),但为了与父类联系需要加入一个外键(pidid)指向父类映射成的表(animal),字段为子类的扩展属性。
Bird子类同样也映射成一张表(bird),也加入一个外键(birdid)指向父类映射成的表(animal),字段为子类的扩展属性。

父类
Animal
package com.liuhao.hibernate4.demo.inherit.joined;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Animal.java
* @2015年7月2日 @下午2:38:21
* @version
* @comments 具体表继承父类
*/
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Animal {
private int id;
private String name;
private boolean sex;
 
public Animal(){};
 
public Animal(int id, String name, boolean sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
 
@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;
}
 
public boolean isSex() {
return sex;
}
 
public void setSex(boolean sex) {
this.sex = sex;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("id", id);
builder.append("name", name);
builder.append("sex", sex);
return builder.toString();
}
}

子类:
Bird
package com.liuhao.hibernate4.demo.inherit.joined;
 
import javax.persistence.Entity;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Bird.java
* @2015年7月2日 @下午2:38:34
* @version
* @comments 具体表继承子类
*/
@Entity
public class Bird extends Animal {
private int height;
 
public int getHeight() {
return height;
}
 
public void setHeight(int height) {
this.height = height;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("height", height);
return builder.toString();
}
 
}

Pig
package com.liuhao.hibernate4.demo.inherit.joined;
 
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Pig.java
* @2015年7月2日 @下午2:38:49
* @version
* @comments 具体表继承子类
*/
@Entity
public class Pig extends Animal {
private int weight;
 
public int getWeight() {
return weight;
}
 
public void setWeight(int weight) {
this.weight = weight;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("weight", weight);
return builder.toString();
}
}

导出数据库表
CREATE TABLE `animal` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
 
CREATE TABLE `bird` (
`height` int(11) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_98gbwudq8mjdefuqcd1tvsb09` FOREIGN KEY (`id`) REFERENCES `animal` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `pig` (
`weight` int(11) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_fls50krk7jm94r9lb2edpwqmd` FOREIGN KEY (`id`) REFERENCES `animal` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Animal

Bird

Pig



1. 数据插入
 
/**
* 数据插入
*
* 子类插入行,都会在父类先插入对应数据
* 控制台输出:
*
* ===========insert===========
Hibernate:
insert
into
Animal
(name, sex)
values
(?, ?)
Hibernate:
insert
into
Animal
(name, sex)
values
(?, ?)
Hibernate:
insert
into
Pig
(weight, id)
values
(?, ?)
Hibernate:
insert
into
Animal
(name, sex)
values
(?, ?)
Hibernate:
insert
into
Bird
(height, id)
values
(?, ?)
2015-07-02 14:59:00,717 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.joined.Animal@5dfaf1[id=5,name=老虎,sex=true]
2015-07-02 14:59:00,717 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Pig com.liuhao.hibernate4.demo.inherit.joined.Pig@159e6e8[weight=200]
2015-07-02 14:59:00,717 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Bird com.liuhao.hibernate4.demo.inherit.joined.Bird@a6af6e[height=30]
===========insert end===========
*/
@Test
public void testInsert() {
System.out.println("===========insert===========");
session.beginTransaction();
 
Animal animal = new Animal();
 
animal.setName("老虎");
animal.setSex(true);
 
Pig pig = new Pig();
 
pig.setName("猪");
pig.setSex(true);
pig.setWeight(200);
 
Bird bird = new Bird();
bird.setName("鸟");
bird.setSex(false);
bird.setHeight(30);
 
session.saveOrUpdate(animal);
session.saveOrUpdate(pig);
session.saveOrUpdate(bird);
 
session.flush();
session.getTransaction().commit();
 
log.debug("Animal " + animal);
log.debug("Pig " + pig);
log.debug("Bird " + bird);
 
System.out.println("===========insert end===========");
}

2. 数据加载
 
/**
* 数据插入
*
* 子类插入行,都会在父类先插入对应数据
* 控制台输出:
* ===========Get===========
Hibernate:
select
animal0_.id as id1_0_0_,
animal0_.name as name2_0_0_,
animal0_.sex as sex3_0_0_,
animal0_1_.weight as weight1_2_0_,
animal0_2_.height as height1_1_0_,
case
when animal0_1_.id is not null then 1
when animal0_2_.id is not null then 2
when animal0_.id is not null then 0
end as clazz_0_
from
Animal animal0_
left outer join
Pig animal0_1_
on animal0_.id=animal0_1_.id
left outer join
Bird animal0_2_
on animal0_.id=animal0_2_.id
where
animal0_.id=?
Hibernate:
select
pig0_.id as id1_0_0_,
pig0_1_.name as name2_0_0_,
pig0_1_.sex as sex3_0_0_,
pig0_.weight as weight1_2_0_
from
Pig pig0_
inner join
Animal pig0_1_
on pig0_.id=pig0_1_.id
where
pig0_.id=?
Hibernate:
select
bird0_.id as id1_0_0_,
bird0_1_.name as name2_0_0_,
bird0_1_.sex as sex3_0_0_,
bird0_.height as height1_1_0_
from
Bird bird0_
inner join
Animal bird0_1_
on bird0_.id=bird0_1_.id
where
bird0_.id=?
2015-07-02 15:03:50,149 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Animal com.liuhao.hibernate4.demo.inherit.joined.Animal@9b1670[id=5,name=老虎,sex=true]
2015-07-02 15:03:50,150 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Pig com.liuhao.hibernate4.demo.inherit.joined.Pig@58dd2d[weight=200]
2015-07-02 15:03:50,150 [com.liuhao.hibernate4.demo.inherit.test.InheritJoinedTest]-[DEBUG] Bird com.liuhao.hibernate4.demo.inherit.joined.Bird@159e6e8[height=30]
===========Get end===========
*/
@Test
public void testGet() {
System.out.println("===========Get===========");
session.beginTransaction();
 
Animal animal = (Animal) session.get(Animal.class, 5);
Pig pig = (Pig) session.get(Pig.class, 6);
Bird bird = (Bird) session.get(Bird.class, 7);
 
session.flush();
session.getTransaction().commit();
 
log.debug("Animal " + animal);
log.debug("Pig " + pig);
log.debug("Bird " + bird);
 
System.out.println("===========Get end===========");
}

单表继承和具体表区别?
1. 单表继承效率高,但是有多余字段
2. 具体表结构分明


(四)类表继承(com.liuhao.hibernate4.demo.table_per_class)
每个具体类映射成一个表(table per concreteclass)(有一些限制)
 
对象模型不用变化,存储模型需要变化

1. 关系模型:
每个具体类(Pig、Brid)映射成一个表(table per concrete class)(有一些限制)


实体类:
Animal
因为子类表的ID是不可以重复,所以一般的主键生成策略已经不适应了,只有表主键生成策略。
因为父类表没有任何作用 所以将此类设置为abstract
package com.liuhao.hibernate4.demo.inherit.table_per_class;
 
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;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Animal.java
* @2015年7月2日 @下午2:38:21
* @version
* @comments 类表继承 父类
*/
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@TableGenerator(
name="t_generator",
table="t_table",
pkColumnName="t_pk",
valueColumnName="t_value",
pkColumnValue="id_pk",
initialValue=1,
allocationSize=1
)
public abstract class Animal {
private int id;
private String name;
private boolean sex;
 
public Animal(){};
 
public Animal(int id, String name, boolean sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
 
@Id
@GeneratedValue(generator="t_generator",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;
}
 
public boolean isSex() {
return sex;
}
 
public void setSex(boolean sex) {
this.sex = sex;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("id", id);
builder.append("name", name);
builder.append("sex", sex);
return builder.toString();
}
}

Bird
package com.liuhao.hibernate4.demo.inherit.table_per_class;
 
import javax.persistence.Entity;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Bird.java
* @2015年7月2日 @下午2:38:34
* @version
* @comments 类表继承 子类
*/
@Entity
public class Bird extends Animal {
private int height;
 
public int getHeight() {
return height;
}
 
public void setHeight(int height) {
this.height = height;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("height", height);
return builder.toString();
}
 
}

Pig
package com.liuhao.hibernate4.demo.inherit.table_per_class;
 
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
/**
* @author liuhao
* @com.liuhao.hibernate4.demo.inherit.singletable
* @Pig.java
* @2015年7月2日 @下午2:38:49
* @version
* @comments 类表继承 子类
*/
@Entity
public class Pig extends Animal {
private int weight;
 
public int getWeight() {
return weight;
}
 
public void setWeight(int weight) {
this.weight = weight;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("weight", weight);
return builder.toString();
}
}

导出数据库表:
CREATE TABLE `bird` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`height` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `pig` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`weight` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
BIrd表


Pig表


Table主键策略表 
初始化为2 因为一开始执行一次



Insert和Get操作
 
/**
* Table_Per_Class 类表继承
*
* 控制台输出:
* Table_Per_Class只能使用table主键生成策略,
* 所以每次insert都会select table主键生成表 再update此表
* 最后insert到当前表中
*/
@Test
public void testInsert() {
System.out.println("===========Insert===========");
session.beginTransaction();
 
Pig p1 = new Pig();
p1.setName("p1");
p1.setSex(true);
p1.setWeight(200);
 
Bird b1 = new Bird();
b1.setName("b1");
b1.setSex(false);
b1.setHeight(30);
 
session.saveOrUpdate(p1);
session.saveOrUpdate(b1);
 
log.debug("Pig extends Animal" + p1);
log.debug("Bird extends Animal" + b1);
 
session.flush();
session.getTransaction().commit();
System.out.println("===========Insert End===========");
}
 
@Test
public void testGet() {
System.out.println("===========Get===========");
session.beginTransaction();
Pig pig = (Pig) session.get(Pig.class, 3);
Bird bird = (Bird) session.get(Bird.class, 4);
session.flush();
session.getTransaction().commit();
log.debug("Pig " + pig);
log.debug("Bird " + bird);
System.out.println("===========Get end===========");
}

总结:
三种继承
第一种:它把所有的数据都存入一个表中,优点:效率好(操作的就是一个表);缺点:存在庸于字段,如果将庸于字段设置为非空,则就无法存入数据;
第二种:层次分明,缺点:效率不好(表间存在关联表)
第三种:主键字段不可以设置为自增主键生成策略。

一般使用第一种

继承类型数据库表父类子类single table 单表
CREATE TABLE `animal` (
`type` varchar(31) NOT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`weight` int(11) DEFAULT NULL,
`height` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",
discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value = "animal")
public class Animal {
private int id;
private String name;
private boolean sex;
@Id
@GeneratedValue
public int getId() {
return id;
}
@Entity
@DiscriminatorValue(value = "bird")
public class Bird extends Animal {
private int height;
joined 具体表继承
CREATE TABLE `animal` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
 
CREATE TABLE `bird` (
`height` int(11) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_98gbwudq8mjdefuqcd1tvsb09` FOREIGN KEY (`id`) REFERENCES `animal` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `pig` (
`weight` int(11) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_fls50krk7jm94r9lb2edpwqmd` FOREIGN KEY (`id`) REFERENCES `animal` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Animal

Bird

Pig


@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Animal {
private int id;
private String name;
private boolean sex;
@Id
@GeneratedValue
public int getId()

@Entity
public class Bird extends Animal {
private int height;

类表继承
CREATE TABLE `bird` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`height` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `pig` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sex` bit(1) NOT NULL,
`weight` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
BIrd表


Pig表


Table主键策略表 
初始化为2 因为一开始执行一次


@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@TableGenerator(
name="t_generator",
table="t_table",
pkColumnName="t_pk",
valueColumnName="t_value",
pkColumnValue="id_pk",
initialValue=1,
allocationSize=1
)
public abstract class Animal {
private int id;
private String name;
private boolean sex;
@Id
@GeneratedValue(generator="t_generator",strategy=GenerationType.TABLE)
public int getId() {
return id;
}

 
@Entity
public class Bird extends Animal {
private int height;





(五)树形结构(comliuhao.demo.node)

Node
package com.liuhao.hibernate4.demo.node;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
 
import org.apache.commons.lang3.builder.ToStringBuilder;
 
@Entity
public class Node {
private int id; // 标识符
private String name; // 节点名称
private int level; // 层次,为了输出设计
private boolean leaf; // 是否为叶子节点,这是为了效率设计,可有可无
// 父节点:因为多个节点属于一个父节点,因此用hibernate映射关系说是“多对一”
private Node parent;
// 子节点:因为一个节点有多个子节点,因此用hibernate映射关系说是“一对多”
private Set<Node> children = new HashSet<Node>();
 
@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;
}
 
public int getLevel() {
return level;
}
 
public void setLevel(int level) {
this.level = level;
}
 
public boolean isLeaf() {
return leaf;
}
 
public void setLeaf(boolean leaf) {
this.leaf = leaf;
}
 
@ManyToOne
@JoinColumn(name="pid")
public Node getParent() {
return parent;
}
 
public void setParent(Node parent) {
this.parent = parent;
}
 
@OneToMany(mappedBy = "parent")
public Set<Node> getChildren() {
return children;
}
 
public void setChildren(Set<Node> children) {
this.children = children;
}
 
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("id", id);
builder.append("name", name);
builder.append("level", level);
builder.append("leaf", leaf);
builder.append("parent", parent);
builder.append("children", children);
return builder.toString();
}
 
}

测试类
@Test
public void testInsert(){
System.out.println("==========================");
session.beginTransaction();
Node root = new Node();
root.setName("root");
 
Node n1 = new Node();
n1.setName("n1");
Node n2 = new Node();
n2.setName("n2");
Node n11 = new Node();
n11.setName("n11");
Node n12 = new Node();
n12.setName("n12");
root.getChildren().add(n1);
root.getChildren().add(n2);
n1.getChildren().add(n11);
n1.getChildren().add(n12);
n11.setParent(n1);
n12.setParent(n1);
n1.setParent(root);
n2.setParent(root);
session.saveOrUpdate(root);
session.saveOrUpdate(n1);
session.saveOrUpdate(n2);
session.saveOrUpdate(n11);
session.saveOrUpdate(n12);
session.getTransaction().commit();
log.debug("root "+root);
log.debug("n1 "+n1);
log.debug("n2 "+n2);
log.debug("n11 "+n11);
log.debug("n12 "+n12);
System.out.println("==========================");
}
 
/**
* 导出
*/
@Test
public void testGet() {
System.out.println("==========================");
session.beginTransaction();
List list = session.createQuery("from Node").list();
for(Iterator it = list.iterator();it.hasNext();)
{
Node node = (Node) it.next();
System.out.println("Node :"+node);
}
session.getTransaction().commit();
System.out.println("==========================");
}



HibernateUtil
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
<session-factory>
 
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/forum</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="connection.pool_size">10</property>
 
<mapping class="com.liuhao.hibernate4.demo.entity.User"></mapping>
<!-- 一对一单向主键 -->
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.primary.oneway.Person11pk"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.primary.oneway.Address11pk"></mapping>
<!-- 一对一双向主键 -->
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.primary.bothway.Wife"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.primary.bothway.Husband"></mapping>
<!-- 一对一单向外键 -->
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.foreign.oneway.IdCard"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.foreign.oneway.Person"></mapping>
<!-- 一对一双向外键 -->
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.foreign.bothway.Student"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.onetoone.foreign.bothway.StuIdCard"></mapping>
<!-- 联合主键 -->
<mapping class="com.liuhao.hibernate4.demo.entity.component.Employee"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.component.User"></mapping>
<!-- 多对一单向 -->
<mapping class="com.liuhao.hibernate4.demo.entity.manytoone.oneway.Group"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.manytoone.oneway.User"></mapping>
<!-- 多对一双向
<mapping class="com.liuhao.hibernate4.demo.entity.manytoone.bothway.Group"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.manytoone.bothway.User"></mapping>
-->
<!-- 多对多单向
<mapping class="com.liuhao.hibernate4.demo.entity.manytomany.oneway.Role"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.manytomany.oneway.User"></mapping>
-->
<!-- 多对多双向 -->
<mapping class="com.liuhao.hibernate4.demo.entity.manytomany.bothway.Role"></mapping>
<mapping class="com.liuhao.hibernate4.demo.entity.manytomany.bothway.User"></mapping>
<!-- 测试
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Husband_111p"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Wife_111p"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Husband_112p"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Wife_112p"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Husband_112f"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Wife_112f"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Husband_m12"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Wife_m12"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Husband_mm2"></mapping>
<mapping class="com.liuhao.hibernate4.demo.mappingtest.Wife_mm2"></mapping>
-->
</session-factory>
 
</hibernate-configuration>

原创粉丝点击