1.Hibernate中提供的三种继承映射关系.
2.重点掌握识别器的映射操作(第三种继承映射)
继承的操作之中,关注的是表的继承与类的继承对应关系,在整个Hibernate里面一共支持有如下几种继承映射关系
●UNION-CLASS:每个继承子表对应一个实体类;
●SUBCLASS:连接子类策略,识别器.(重点)
●JOINED-SUBCLASS:每个类对应一张数据表,数据表中存在有继承关系
继承形式一:UNION-CLASS
这种的继承关系重点只在程序的维护上,而数据表上依然会存在有重复数据;
创建web项目:HibernateSubclass
创建两张表
分别创建两个表的实体类,但是需要他们有共同的部分mid,name,age,提取出来创建父类
父类定义如下
package cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
/**
* Student entity. @author MyEclipse Persistence Tools
*/
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Member implements java.io.Serializable {
// Fields
private String mid;
private String name;
private Integer age;
// Constructors
/** default constructor */
public Member() {
}
/** full constructor */
public Member(String mid, String name, Integer age, String school, Double score) {
this.mid = mid;
this.name = name;
this.age = age;
}
// Property accessors
@Id
@Column(name = "mid", unique = true, nullable = false)
public String getMid() {
return this.mid;
}
public void setMid(String mid) {
this.mid = mid;
}
@Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "age", nullable = false)
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
以上注解表示定义的策略为一张表一个类的原则,在其他的worker类里面和stuent类里面同时写上此注解
package cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
/**
* Student entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "student", catalog = "aaa")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Student extends Member implements java.io.Serializable {
private String school;
private Double score;
// Constructors
/** default constructor */
public Student() {
}
/** full constructor */
public Student(String mid, String name, Integer age, String school, Double score) {
this.school = school;
this.score = score;
}
@Column(name = "school", nullable = false)
public String getSchool() {
return this.school;
}
public void setSchool(String school) {
this.school = school;
}
@Column(name = "score", nullable = false, precision = 22, scale = 0)
public Double getScore() {
return this.score;
}
public void setScore(Double score) {
this.score = score;
}
}
package cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
/**
* Worker entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "worker", catalog = "aaa")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Worker extends Member implements java.io.Serializable {
private String company;
private Double salary;
// Constructors
/** default constructor */
public Worker() {
}
// Property accessors
@Column(name = "company", nullable = false)
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
@Column(name = "salary", nullable = false, precision = 22, scale = 0)
public Double getSalary() {
return this.salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
并在hibernate.cfg.xml里面添加mapping的class映射,
<mapping class="cn.zwb.pojo.Member" />
此时就完成了表的配置,编写测试类测试
package cn.zwb.test;
import cn.mldn.dbc.HibernateSessionFactory;
import cn.zwb.pojo.Student;
public class Test {
public static void main(String[] args) {
Student stu =new Student();
stu.setAge(100);
stu.setMid("666");
stu.setName("zwb");
stu.setSchool("河南机电");
stu.setScore(100.0);
HibernateSessionFactory.getSession().save(stu);
HibernateSessionFactory.getSession().beginTransaction().commit();
HibernateSessionFactory.closeSession();
}
}
继承形式二:JOINED-SUBCLASS
开发里面必须要回避几个问题:多表查询,1+n此查询,略
继承形式二:JOINED-SUBCLASS
●继承形式一(UNION):只在类结构上实现了继承以及结构的通用,但是在数据表的操作上依然会出现重复的字段,所以设计上不好;
●继承形式二(JOINED):在数据比啊的设计上产生了继承的关系,可是结果发现在进行数据查询的时候会存在有多表查询的操作关系.
●所以就发现以上的两种继承结构实际上都不好使用,那么在实际的工作之中往往会使用第三种继承关系--识别器,也就是说这些具备有类继承关系的结构定义在一张数据表中,随后使用一个字段作为区分符
继承形式二:SUBCLASS
首先创建数据表member_subclass
type字段由hibernate进行维护
而后使用myeclipse生成pojo类,
修改pojo类MemberSubClass;只保留公共部分 mid,name,age,并且加上abstract,加上abstract的原因是使此类不能直接使用,而通过继承使用,
package cn.zwb.pojo;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
public class MamberSubclass implements java.io.Serializable {
// Fields
private String mid;
private String name;
private Integer age;
// Constructors
/** default constructor */
public MamberSubclass() {
}
/** minimal constructor */
public MamberSubclass(String mid) {
this.mid = mid;
}
/** full constructor */
// Property accessors
public String getMid() {
return this.mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
然后创建Student和Worker类并继承,MamberSubclass类
package cn.zwb.pojo;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
@SuppressWarnings("serial")
public class Student extends MamberSubclass implements java.io.Serializable {
// Fields
private Double score;
private String school;
// Constructors
/** default constructor */
public Student() {
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
/** minimal constructor */
}
package cn.zwb.pojo;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
public class Worker extends MamberSubclass implements java.io.Serializable {
// Fields
private String company;
private Double salary;
// Constructors
/** default constructor */
public Worker() {
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
创建过后在MamberSubclass.hbm.xml文件中配置
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="cn.zwb.pojo.MamberSubclass" table="mamber_subclass" catalog="aaa">
<id name="mid" type="java.lang.String">
<column name="mid" length="50" />
<generator class="assigned"></generator>
</id>
<!--自定义识别字段 需要由hibernate自己维护type -->
<discriminator column="type" type="java.lang.String"/>
<property name="name" type="java.lang.String">
<column name="name" length="50" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" />
</property>
<subclass name="cn.zwb.pojo.Student" discriminator-value="学生">
<property name="score" type="java.lang.Double">
<column name="score" precision="22" scale="0" />
</property>
<property name="school" type="java.lang.String">
<column name="school" length="50" />
</property>
</subclass>
<subclass name="cn.zwb.pojo.Worker" discriminator-value="工人">
<property name="salary" type="java.lang.Double">
<column name="salary" precision="22" scale="0" />
</property>
<property name="company" type="java.lang.String">
<column name="company" length="50" />
</property>
</subclass>
</class>
</hibernate-mapping>
此标签表示为自定义识别字段 需要由hiberante自己维护
<discriminator column="type" type="java.lang.String"/>
然后在里面定义Student类
<subclass name="cn.zwb.pojo.Student" discriminator-value="学生">
<property name="score" type="java.lang.Double">
<column name="score" precision="22" scale="0" />
</property>
<property name="school" type="java.lang.String">
<column name="school" length="50" />
</property>
</subclass>
接着定义Worker类
<subclass name="cn.zwb.pojo.Worker" discriminator-value="工人">
<property name="salary" type="java.lang.Double">
<column name="salary" precision="22" scale="0" />
</property>
<property name="company" type="java.lang.String">
<column name="company" length="50" />
</property>
</subclass>
此时就完成了基于*.hbm,xml文件的配置
编写测试类
package cn.zwb.test;
import cn.mldn.dbc.HibernateSessionFactory;
import cn.zwb.pojo.Student;
import cn.zwb.pojo.Worker;
public class Test {
public static void main(String[] args) {
Worker stu =new Worker();
stu.setAge(100);
stu.setMid("86776");
stu.setName("zwb");
stu.setCompany("公司");
stu.setSalary(133.1);
HibernateSessionFactory.getSession().save(stu);
HibernateSessionFactory.getSession().beginTransaction().commit();
HibernateSessionFactory.closeSession();
}
}
然后就存入进去了
\
此时的SQL语句为
type字段的内容由Hiberante自己负责维护,而用户不需要知道它的存在,这一点的设计是实体层开发框架里面最为智能的一个
基于Anntation的配置
早JPA的标准里面支持有Annotation的操作配置,大部分都需要用户自己来手工完成
首先创建MemberSubclass类
package cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "mamber_subclass", catalog = "aaa")
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
public abstract class MamberSubclass implements java.io.Serializable {
// Fields
private String mid;
private String name;
private Integer age;
// Constructors
/** default constructor */
public MamberSubclass() {
}
/** minimal constructor */
public MamberSubclass(String mid) {
this.mid = mid;
}
@Id
@Column(name = "mid", unique = true, nullable = false, length = 50)
public String getMid() {
return this.mid;
}
public void setMid(String mid) {
this.mid = mid;
}
@Column(name = "name", length = 50)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "age")
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
而后在此类上定义此注解
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
同时创建Strudent与Worker子类
package cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
@Entity
@DiscriminatorValue("学生")
public class Student extends MamberSubclass implements java.io.Serializable {
private Double score;
private String school;
@Column(name = "score", precision = 22, scale = 0)
public Double getScore() {
return this.score;
}
public void setScore(Double score) {
this.score = score;
}
@Column(name = "school", length = 50)
public String getSchool() {
return this.school;
}
public void setSchool(String school) {
this.school = school;
}
}
ackage cn.zwb.pojo;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
/**
* MamberSubclass entity. @author MyEclipse Persistence Tools
*/
@Entity
@DiscriminatorValue("工人")
public class Worker extends MamberSubclass implements java.io.Serializable {
// Fields
private String company;
private Double salary;
// Constructors
/** default constructor */
public Worker() {
}
@Column(name = "company", length = 50)
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
@Column(name = "salary", precision = 22, scale = 0)
public Double getSalary() {
return this.salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
分别添加此注解
@DiscriminatorValue("工人")
@DiscriminatorValue("学生")
最后在hibernate.cfg.xml里面配置如下
<mapping class="cn.zwb.pojo.MamberSubclass" />
<mapping class="cn.zwb.pojo.Student" />
<mapping class="cn.zwb.pojo.Worker" />
此时配置完成,这种识别器的操作模式在实际开发之中使用的非常的多,在整个继承关系之中,识别器是一个非常重要的概念,同时Hiberante自动维护识别字段,不是所有框架都支持自动识别维护字段
总结
识别器非常重要必须掌握,
三种继承映射都具备同一个特点,类的继承结构永远保持不变,唯一改变的只是表的结构关系以及配置的定义部分