一、关联映射
+++ 关联映射
1.一对多、多对一映射
案例: 部门与员工
表结构:
两张表。(主表、外键表)
部门表的主键约束员工表的外键字段
映射:
配置主表与外键表的映射文件
b.多对多映射
案例: 开发者与项目组
表结构:
三张表(两张主表、关联关系表)
(开发者表、项目表、开发者与项目的关联关系表)
映射:
配置开发者表映射、项目表映射
c.一对一映射
案例: 用户与身份证信息
表结构:
两张表(主表、外键表)
一条用户信息对应一条身份证信息 【一对一】
映射:
配置两个映射文件。
分类:
一对一映射有两种方式:
1.基于外键的映射
主键表约束外键表,外键是普通字段
2.基于主键的映射
主键表约束外键表,外键是外键表的主键
e.组件映射、继承映射
一对多:
<set name="映射的集合属性" table="(可选)集合属性对应的外键表">
<key column="外键表的,外键字段" />
<one-to-many class="集合元素的类型" />
</set>
多对一:
<many-to-one name="对象属性" class="对象类型" column="外键字段字段" />
多对多
<set name="" table="">
<key column="" />
<many-to-many column="" class="">
</set>
1.1 一对多、多对一映射
实体:
public class DeptEntity {
private int deptId;
private String deptName;
private String deptCode;
//一对多映射
private Set<EmpEntity> empSet;
}
public class EmpEntity {
private int id;
private String name;
private String desc;
//多对一
private DeptEntity dept;
}
映射:
Dept.hbm.xml(主表,一对多)
key关键字: 映射的是外键表的外键字段
one-to-many: 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名
<!-- set 映射外键表 -->
<set name="empSet" >
<key column="t_deptId1"></key>
<one-to-many class="EmpEntity"></one-to-many>
</set>
Emp.hbm.xml(外键表,多对一)
name="dept" 映射的部门属性
<!--
多对一映射配置
Employee 映射关键点:
1. 映射的部门属性 : dept
2. 映射的部门属性,对应的外键字段: dept_id
3. 部门的类型
-->
<many-to-one name="dept" column="t_deptId1" class="DeptEntity"></many-to-one>
2.1.1 数据库表结构
>>>>>> 部门表
>>>>>> 员工表
2.1.2 示例
>>>>>> Dept.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.d_one2Many" >
<class name="DeptEntity" table="t_dept">
<id name="deptId" column="t_id" >
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="deptName" column="t_name"></property>
<property name="deptCode" column="t_code"></property>
<!--
一对多关联映射配置 (通过部门管理到员工)
Dept 映射关键点:
1. 指定 映射的集合属性: "emps"
2. 集合属性对应的集合表: "t_employee"
3. 集合表的外键字段 "t_employee. dept_id"
4. 集合元素的类型
inverse=false set集合映射的默认值; 表示有控制权
<set name="empSet" table="t_emp">
-->
<set name="empSet" >
<key column="t_deptId1"></key>
<!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 -->
<one-to-many class="EmpEntity"></one-to-many>
</set>
</class>
</hibernate-mapping>
>>>>>> DeptEntity .java
public class DeptEntity {
private int deptId;
private String deptName;
private String deptCode;
//一对多映射
private Set<EmpEntity> empSet;
}
>>>>>> EmpEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.d_one2Many" >
<class name="EmpEntity" table="t_emp">
<id name="id" column="t_empId" >
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="t_empName"></property>
<property name="desc" column="t_desc"></property>
<!--
多对一映射配置
Employee 映射关键点:
1. 映射的部门属性 : dept
2. 映射的部门属性,对应的外键字段: dept_id
3. 部门的类型
-->
<many-to-one name="dept" column="t_deptId1" class="DeptEntity"></many-to-one>
</class>
</hibernate-mapping>
>>>>>> EmpEntity.java
public class EmpEntity {
private int id;
private String name;
private String desc;
//多对一
private DeptEntity dept;
}
>>>>>> App.java
public class App3 {
private static Session session;
static {
session= new Configuration().configure()
.addClass(EmpEntity.class)
.addClass(DeptEntity.class)
.buildSessionFactory()
.openSession();
}
public static void main(String[] args) {
save2();
}
/**
* 从部门的角度维度数据【从一的方向维护关系】
*/
private static void save1() {
Set<EmpEntity> empSet=new HashSet<EmpEntity>();
EmpEntity emp=new EmpEntity();
emp.setName("xxx1");
emp.setDesc("1");
empSet.add(emp);
EmpEntity emp2=new EmpEntity();
emp2.setName("xxx2");
emp2.setDesc("2");
empSet.add(emp2);
//从一的方向保存数据
DeptEntity dept=new DeptEntity();
dept.setDeptCode("001");
dept.setDeptName("develop");
dept.setEmpSet(empSet);
Transaction tr = session.beginTransaction();
session.save(emp);
session.save(emp2);
session.save(dept);
tr.commit();
}
/**
* 从员工的角度维度数据【从多的方向维护关系,推荐】
*/
private static void save2() {
DeptEntity dept=new DeptEntity();
dept.setDeptCode("001");
dept.setDeptName("develop");
EmpEntity emp=new EmpEntity();
emp.setName("xxx1");
emp.setDesc("1");
emp.setDept(dept);
EmpEntity emp2=new EmpEntity();
emp2.setName("xxx2");
emp2.setDesc("2");
emp2.setDept(dept);
Transaction tr = session.beginTransaction();
session.save(dept);
session.save(emp);
session.save(emp2);
tr.commit();
}
}
2.1.3 关键字
案例:部门与员工
inverse关键字设置到set节点上,作用是设置控制权:
<set name="empSet" inverse="true" >
<key column="t_deptId1"></key>
<!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 -->
<one-to-many class="EmpEntity"></one-to-many>
</set>
1.inverse=false,有控制权。
可以从配置的一方维护关联关系。
保存数据
清除关联关系
删除数据
2.inverse=true,无控制权。
不可以从配置的一方维护关联关系。
不能保存数据
不能清除关联关系
不能删除数据
cascade关键字可以设置到set节点、many-to-one节点上,设置级联操作:
设置到set节点上:
<set name="empSet" cascade="delete" >
<key column="t_deptId1"></key>
<!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 -->
<one-to-many class="EmpEntity"></one-to-many>
</set>
设置到many-to-one节点上:
<many-to-one name="dept" column="t_deptId1" class="DeptEntity" cascade="delete" ></many-to-one>
1.2 多对多映射
实体:
public class DeveloperEnTity {
private int id;
private String name;
private int age;
//多对多
private Set<ProjectEntity> projectSet;
}
public class ProjectEntity {
private int pId;
private String pName;
private String pDesc;
//多对多映射
private Set<DeveloperEnTity> developerSet;
}
映射:
多对多映射,双方的映射配置都是映射的第三张关联表
DeveloperEnTity.hbm.xml(主表)
key关键字: 映射的是外键表的外键字段
many-to-many: 映射外键表的第二个外键字段。(column指定第二个外键字段的名称。class指定第二个外键字段的来演)
<set name="projectSet" table="t_pro_dev" >
<key column="t_developerId"></key>
<many-to-many column="t_projectId" class="ProjectEntity"></many-to-many>
</set>
ProjectEntity.hbm.xml(主表)
key关键字: 映射的是外键表的外键字段
many-to-many: 映射外键表的第二个外键字段。(column指定第二个外键字段的名称。class指定第二个外键字段的来演)
<set name="developerSet" table="t_pro_dev" >
<key column="t_projectId"></key>
<many-to-many column="t_developerId" class="DeveloperEnTity"></many-to-many>
</set>
1.2.1 数据库表结构
>>>>>> 开发者表
>>>>>> 项目表
>>>>>> 关联表
2.1.2 示例
>>>>>> DeveloperEnTity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.e_many2Many" >
<class name="DeveloperEnTity" table="t_developer">
<id name="id" column="t_id" >
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="t_name"></property>
<property name="age" column="t_age"></property>
<set name="projectSet" table="t_pro_dev" >
<key column="t_developerId"></key>
<many-to-many column="t_projectId" class="ProjectEntity"></many-to-many>
</set>
</class>
</hibernate-mapping>
>>>>>> DeveloperEnTity .java
public class DeveloperEnTity {
private int id;
private String name;
private int age;
//多对多
private Set<ProjectEntity> projectSet=new HashSet<ProjectEntity>();
}
>>>>>> ProjectEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.e_many2Many" >
<class name="ProjectEntity" table="t_project" >
<id name="pId" column="t_id" >
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="pName" column="t_name"></property>
<property name="pDesc" column="t_desc"></property>
<set name="developerSet" table="t_pro_dev" >
<key column="t_projectId"></key>
<many-to-many column="t_developerId" class="DeveloperEnTity"></many-to-many>
</set>
</class>
</hibernate-mapping>
>>>>>> ProjectEntity .java
public class ProjectEntity {
private int pId;
private String pName;
private String pDesc;
//多对多映射
private Set<DeveloperEnTity> developerSet=new HashSet<DeveloperEnTity>();
}
>>>>>> App.java
public class App {
private static Session session;
static {
session= new Configuration().configure()
.addClass(DeveloperEnTity.class)
.addClass(ProjectEntity.class)
.buildSessionFactory()
.openSession();
}
/**
* list查询
* @param args
*/
public static void main(String[] args) {
save();
}
public void testGet() {
}
/**
* 多对多保存数据【只能通过一方维护另一方,不能重复维护,否则报错。】
* @param args
*/
private static void save() {
//开发者1
DeveloperEnTity developer=new DeveloperEnTity();
developer.setName("小白");
//开发者2
DeveloperEnTity developer2=new DeveloperEnTity();
developer2.setName("小白2");
//项目
ProjectEntity pro=new ProjectEntity();
pro.setpName("MRP");
//维护关系
pro.getDeveloperSet().add(developer);
pro.getDeveloperSet().add(developer2);
//保存数据
session.beginTransaction();
session.save(developer);
session.save(developer2);
session.save(pro);
session.getTransaction().commit();
}
/**
* 多对多保存数据【在项目一方设置级联操作】
* @param args
*/
private static void save2() {
//开发者1
DeveloperEnTity developer=new DeveloperEnTity();
developer.setName("小白");
//开发者2
DeveloperEnTity developer2=new DeveloperEnTity();
developer2.setName("小白2");
//项目
ProjectEntity pro=new ProjectEntity();
pro.setpName("MRP");
//维护关系
pro.getDeveloperSet().add(developer);
pro.getDeveloperSet().add(developer2);
//保存数据
session.beginTransaction();
// session.save(developer);
// session.save(developer2);
session.save(pro);//必须设置级联操作
session.getTransaction().commit();
}
}
1.3 一对一映射
1.3.1 主键表映射外键表的外键字段,外键字段为普通字段
实体:
public class User {
private String userId;
private String name;
private int age;
private Card card;
}
public class Card {
private String cardNum;
private String place;
private User user;
}
映射:
User.hbm.xml(主表)
<one-to-one name="card" class="Card"></one-to-one>
Card.hbm.xml(外键表)
many-to-one: 将一个实体映射为一个外键字段
unique="true" 给外键字段添加唯一约束
<many-to-one name="user" unique="true" column="userId" class="User"></many-to-one>
1.3.1.1 数据库表结构
>>>>>> 用户表
>>>>>> 身份证表
1.3.1.2 示例
>>>>>> User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.i_one2one" >
<class name="User" table="h_user" >
<id name="userId" column="userId">
<generator class="uuid"/>
</id>
<property name="name" column="name"></property>
<property name="age" column="age"></property>
<!-- 一对一映射:没有外键方 -->
<one-to-one name="card" class="Card"></one-to-one>
</class>
</hibernate-mapping>
>>>>>> User .java
public class User {
private String userId;
private String name;
private int age;
private Card card;
}
>>>>>> Card.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.i_one2one" >
<class name="Card" table="h_card" >
<id name="cardNum" column="cardNum">
<generator class="assigned"></generator>
</id>
<!-- 非主键,映射 -->
<property name="place" column="place"></property>
<!-- 一对一映射:有外键方
many-to-one: 将一个实体映射为一个外键字段
unique="true" 给外键字段添加唯一约束
-->
<many-to-one name="user" unique="true" column="userId" class="User"></many-to-one>
</class>
</hibernate-mapping>
>>>>>> Card.java
public class Card {
private String cardNum;
private String place;
private User user;
}
>>>>>> App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Card.class).addClass(User.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//用户
User p=new User();
p.setName("小白");
p.setAge(12);
//身份证
Card c=new Card();
c.setCardNum("320321199401027233");
c.setPlace("xxx");
//关系
c.setUser(p);
//保存
session.save(p);
session.save(c);
tr.commit();
}
}
1.3.2 主键表映射外键表的外键字段,外键字段为主键字段
实体:
public class User {
private String userId;
private String name;
private int age;
private Card card;
}
public class Card {
private String cardNum;
private String place;
private User user;
}
映射:
User.hbm.xml(主表)
<!-- 一对一映射:没有外键方 -->
<one-to-one name="card" class="Card"></one-to-one>
Card.hbm.xml(外键表)
many-to-one: 将一个实体映射为一个外键字段
unique="true" 给外键字段添加唯一约束
<!--
一对一映射:有外键方(基于主键的映射)
constrained="true" 指定在主键上添加外键约束
-->
<one-to-one name="user" constrained="true" class="User"></one-to-one>
1.3.2.1 数据库表结构
>>>>>> 用户表
>>>>>> 身份证表
1.3.2.2 示例
>>>>>> User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.i_one2one" >
<class name="User" table="h_user" >
<id name="userId" column="userId">
<generator class="uuid"/>
</id>
<property name="name" column="name"></property>
<property name="age" column="age"></property>
<!-- 一对一映射:没有外键方 -->
<one-to-one name="card" class="Card"></one-to-one>
</class>
</hibernate-mapping>
>>>>>> User .java
public class User {
private String userId;
private String name;
private int age;
private Card card;
}
>>>>>> Card.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.i_one2one_2" >
<class name="Card" table="h_card" >
<!--
id节点指定的是主键映射,则userId是主键
主键生成方式:foreign,即把别的表的主键作为当前表的主键。
property 指定引用的对象, 引用对象 --》对象全名 --》对象的映射 --》table(id)
根据引用的对象,找到对象的全名 org.jsoft.i_one2one_2.user
根据引用的对象全名,找到引用对象的映射
根据引用的对象映射,找到引用表的ID。
把别的表的主键作为当前表的主键
-->
<id name="userId" column="user_id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<!-- 非主键,映射 -->
<property name="place" column="place"></property>
<property name="cardNum" column="cardNum"></property>
<!--
一对一映射:有外键方(基于主键的映射)
constrained="true" 指定在主键上添加外键约束
-->
<one-to-one name="user" constrained="true" class="User"></one-to-one>
</class>
</hibernate-mapping>
>>>>>> Card.java
public class Card {
private String cardNum;
private String place;
private User user;
}
>>>>>> App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Card.class).addClass(User.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//用户
User p=new User();
p.setName("小白");
p.setAge(12);
//身份证
Card c=new Card();
c.setCardNum("320321199401027233");
c.setPlace("xxx");
//关系
c.setUser(p);
//保存
session.save(p);
session.save(c);
tr.commit();
}
}
二、组件映射
+++ 组合关系
一个类中包含了另外一个类。这2个类中就是组合关系。
需求: 汽车与车轮
2.1 数据库表结构
2.2 示例
Car.java
public class Car {
private String id;
private String name;
private Whele whele;
}
Whele .java
public class Whele {
private int count;
private int size;
private String color;
}
Car.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.j_component" >
<class name="Car" table="t_car" >
<id name="id" column="id">
<generator class="uuid"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<!-- 组件映射 -->
<component name="whele" class="Whele">
<property name="count" column="count"></property>
<property name="size" column="size"></property>
<property name="color" column="color"></property>
</component>
</class>
</hibernate-mapping>
App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Car.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//车轮
Whele whele=new Whele();
whele.setColor("Yellow");
whele.setCount(4);
whele.setSize(14);
//车
Car c=new Car();
c.setName("大众");
c.setWhele(whele);
//保存
session.save(c);
tr.commit();
}
}
三、继承映射
+++ 继承关系
一个类继承另外一个类。这2个类中就是继承关系。
+++ 继承映射:
1.简单继承映射
有多少个子类就有多少个映射文件
2.复杂继承映射
3.1 简单继承映射
实体:
public class Animal {
private int id;
private String name;
private String color;
}
public class Cat extends Animal{
//吃老鼠
private boolean eatMouse;
}
映射文件:
Cat.hbm.xml:
<class name="Cat" table="t_cat" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<property name="eatMouse" column="eatMouse" ></property>
</class>
3.1.1 数据库表结构
3.1.2 示例
>>>>>> Cat.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends1" >
<class name="Cat" table="t_cat" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<property name="eatMouse" column="eatMouse" ></property>
</class>
</hibernate-mapping>
>>>>>> Animal .java
public class Animal {
private int id;
private String name;
private String color;
}
>>>>>> Cat.java
public class Cat extends Animal{
//吃老鼠
private boolean eatMouse;
}
>>>>>> App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Cat.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
save();
}
private static void query() {
Query qr = session.createQuery("from Cat");
List<Cat> list = qr.list();
System.out.println(list);
}
/**
* 保存
*/
private static void save() {
Transaction tr = session.beginTransaction();
Cat c=new Cat();
c.setColor("Yello");
c.setName("小白");
c.setEatMouse(true);
//保存
session.save(c);
tr.commit();
}
}
3.2 复杂继承映射
3.2.1 所有子类都映射都父类映射的表中(一张表,一个映射文件)
应用场景:
子类教多,且子类较为简单,即只有个别属性!
好处:因为使用一个映射文件, 减少了映射文件的个数。
缺点:
1.不符合数据库设计原则.
2.一个映射文件: Animal.hbm.xml (如何区分是哪个子类的信息?)
实体:
public class Animal {
private int id;
private String name;
private String color;
}
public class Cat extends Animal{
//吃老鼠
private String eatMouse;
}
public class Monkey extends Animal{
private String eatBranana;
}
映射文件:Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends2" >
<class name="Animal" table="t_animal" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 指定鉴别器字段 column可写可不写,column默认为class -->
<discriminator column="type"></discriminator>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<!-- 子类:
每个子类都用subclass节点映射
注意:一定要指定鉴别器字段,否则报错。
鉴别器字段的作用是在数据库中区别每一个记录的类型
discriminator-value="cat1"
指定鉴别器字段的值。即鉴别器字段type的值。
如果不指定,默认为该子类的全路径
-->
<subclass name="Cat" discriminator-value="cat1">
<property name="eatMouse" column="eatMouse" ></property>
</subclass>
<!-- 映射子类 -->
<subclass name="Monkey" >
<property name="eatBranana" column="eatBranana" ></property>
</subclass>
</class>
</hibernate-mapping>
3.2.1.1 数据库表结构
3.2.1.2 示例
>>>>>>Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends2" >
<class name="Animal" table="t_animal" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 指定鉴别器字段 column可写可不写,column默认为class -->
<discriminator column="type"></discriminator>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<!-- 子类:
每个子类都用subclass节点映射
注意:一定要指定鉴别器字段,否则报错。
鉴别器字段的作用是在数据库中区别每一个记录的类型
discriminator-value="cat1"
指定鉴别器字段的值。即鉴别器字段type的值。
如果不指定,默认为该子类的全路径
-->
<subclass name="Cat" discriminator-value="cat1">
<property name="eatMouse" column="eatMouse" ></property>
</subclass>
<!-- 映射子类 -->
<subclass name="Monkey" >
<property name="eatBranana" column="eatBranana" ></property>
</subclass>
</class>
</hibernate-mapping>
>>>>>>Animal.java
public class Animal {
private int id;
private String name;
private String color;
}
>>>>>>Cat .java
public class Cat extends Animal{
//吃老鼠
private String eatMouse;
}
>>>>>>Monkey.java
public class Monkey extends Animal{
private String eatBranana;
}
>>>>>>App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Animal.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//猫
Cat c=new Cat();
c.setColor("Yello");
c.setName("小白");
c.setEatMouse("1");
//猴子
Monkey m=new Monkey();
m.setColor("Blue");
m.setName("小黑");
//保存
session.save(c);
session.save(m);
tr.commit();
}
}
3.2.2 每个类各自映射一张表,父类也对应表(N个类N个表)
一个映射文件,存储所有的子类; 子类父类都对应表;
缺点:表结构比较复杂,插入一条子类信息,需要用2条sql:
即往父类插入、往子类插入!
实体:
public class Animal {
private int id;
private String name;
private String color;
}
public class Cat extends Animal{
//吃老鼠
private String eatMouse;
}
public class Monkey extends Animal{
private String eatBranana;
}
映射文件Animal.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends3" >
<class name="Animal" table="t_animal" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<!-- -->
<joined-subclass name="Cat" table="t_cat">
<key column="t_cat_id"></key>
<property name="eatMouse" column="eatMouse"></property>
</joined-subclass>
<joined-subclass name="Monkey" table="t_monkey">
<key column="t_monkey_id"></key>
<property name="eatBranana" column="eatBranana"></property>
</joined-subclass>
</class>
</hibernate-mapping>
3.2.2.1 数据库表结构
>>>>>> Animal 父类动物表
>>>>>> Cat子类表
>>>>>> Monkey子类表
3.2.2.2 示例
>>>>>>Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends3" >
<class name="Animal" table="t_animal" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<!-- -->
<joined-subclass name="Cat" table="t_cat">
<key column="t_cat_id"></key>
<property name="eatMouse" column="eatMouse"></property>
</joined-subclass>
<joined-subclass name="Monkey" table="t_monkey">
<key column="t_monkey_id"></key>
<property name="eatBranana" column="eatBranana"></property>
</joined-subclass>
</class>
</hibernate-mapping>
>>>>>>Animal.java
public class Animal {
private int id;
private String name;
private String color;
}
>>>>>>Cat .java
public class Cat extends Animal{
//吃老鼠
private String eatMouse;
}
>>>>>>Monkey.java
public class Monkey extends Animal{
private String eatBranana;
}
>>>>>>App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Animal.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//猫
Cat c=new Cat();
c.setColor("Yello");
c.setName("小白");
c.setEatMouse("1");
//猴子
Monkey m=new Monkey();
m.setColor("Blue");
m.setName("小黑");
//保存
session.save(c);
session.save(m);
tr.commit();
}
}
3.2.3 每个类各自映射一张表,父类不对应表(N-1表)
3.2.3.1 数据库表结构
>>>>>> Cat子类表
>>>>>> Monkey子类表
3.2.2.2 示例
>>>>>>Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.jsoft.k_entends4" >
<!--
abstract="true"
指定实体类对象不对应表,即在数据库端不生成表。
如果不写这个,则会生成Animal表,但是表为空。
-->
<class name="Animal" abstract="true" >
<!-- 如果用union-subclass 节点,主键生成策略不能为自增长,必须手动指定-->
<id name="id" column="id">
<generator class="uuid"></generator>
</id>
<!-- 非主键,映射 -->
<property name="name" column="name"></property>
<property name="color" column="color"></property>
<!-- -->
<union-subclass name="Cat" table="t_cat">
<property name="eatMouse" column="eatMouse"></property>
</union-subclass>
<union-subclass name="Monkey" table="t_monkey">
<property name="eatBranana" column="eatBranana"></property>
</union-subclass>
</class>
</hibernate-mapping>
>>>>>>Animal.java
public class Animal {
private int id;
private String name;
private String color;
}
>>>>>>Cat .java
public class Cat extends Animal{
//吃老鼠
private String eatMouse;
}
>>>>>>Monkey.java
public class Monkey extends Animal{
private String eatBranana;
}
>>>>>>App.java
public class App {
private static Session session;
static {
SessionFactory sf=new Configuration().configure().addClass(Animal.class).buildSessionFactory();
session = sf.openSession();
}
public static void main(String[] args) {
Transaction tr = session.beginTransaction();
//猫
Cat c=new Cat();
c.setColor("Yello");
c.setName("小白");
c.setEatMouse("1");
//猴子
Monkey m=new Monkey();
m.setColor("Blue");
m.setName("小黑");
//保存
session.save(c);
session.save(m);
tr.commit();
}
}