java继承 映射_Hibernate第九篇【组件映射、继承映射】

前言

到目前位置,我们已经学习了一对一、一对多、多对一、多对多映射了…既然Hibernate是ORM实现的框架,它还提供了组件映射和继承映射..本博文主要讲解组件映射和继承映射

Java主要的类主要有两种方式

组合关系,组合关系对应的就是组件映射

继承关系,继承关系对应的就是继承映射

组件映射

组件映射实际上就是将组合关系的数据映射成一张表,组件类和被包含的组件类映射成一张表

有的时候,两个类的关系明显不是继承关系,但两个类的亲密程度很高,在一个类里边需要用到另外一个类…那么就在类中定义一个变量来维护另一个类的关系,这种就叫组合关系!

需求:汽车和轮子。汽车需要用到轮子,但是轮子的爸爸不可能是汽车吧?

设计数据库

7bbfc4438febe756819542800c3a78ec.png

设计实体

Wheel.java

public class Wheel {

private int count;

private int size;

public int getCount() {

return count;

}

public void setCount(int count) {

this.count = count;

}

public int getSize() {

return size;

}

public void setSize(int size) {

this.size = size;

}

}

Car.java,使用变量维护Wheel

package zhongfucheng.aa;

/**

* Created by ozc on 2017/5/7.

*/

public class Car {

private int id;

private String name;

private Wheel wheel;

public Wheel getWheel() {

return wheel;

}

public void setWheel(Wheel wheel) {

this.wheel = wheel;

}

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;

}

}

映射表

使用了一个新标签,组件映射标签。

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

测试

package zhongfucheng.aa;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

/**

* Created by ozc on 2017/5/6.

*/

public class App5 {

public static void main(String[] args) {

//创建对象

Wheel wheel = new Wheel();

Car car = new Car();

//设置属性

wheel.setCount(43);

wheel.setSize(22);

car.setName("宝马");

//维护关系

car.setWheel(wheel);

//获取加载配置管理类

Configuration configuration = new Configuration();

configuration.configure().addClass(Car.class);

//创建Session工厂对象

SessionFactory factory = configuration.buildSessionFactory();

//得到Session对象

Session session = factory.openSession();

//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

session.save(car);

//提交事务

transaction.commit();

//关闭Session

session.close();

}

}

8cc7be03feafe13fd00f3344bc5e4cf7.png

传统方式继承

需求:动物、猫、猴子。猫继承着动物

传统方式继承的特点就是:有多少个子类就写多少个配置文件.

表结构

我们的表应该是这样的:id和name从Animal中继承,catchMouse是子类的具体行为。

0222562692e1dd2269db8350968d6f71.png

实体

Animal.java

package zhongfucheng.aa;

// 动物类

public abstract class Animal {

private int id;

private String name;

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;

}

}

Cat.java继承着Animail

package zhongfucheng.aa;

public class Cat extends Animal{

// 抓老鼠

private String catchMouse;

public String getCatchMouse() {

return catchMouse;

}

public void setCatchMouse(String catchMouse) {

this.catchMouse = catchMouse;

}

}

映射文件

简单继承的映射文件很好写,在属性上,直接写父类的属性就可以了。

但是也有致命的缺点:如果子类有很多,就需要写很多的配置文件

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

测试

package zhongfucheng.aa;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

public class App5 {

public static void main(String[] args) {

//创建对象

Cat cat = new Cat();

//设置属性

cat.setName("大花猫");

cat.setCatchMouse("捉大老鼠");

//获取加载配置管理类

Configuration configuration = new Configuration();

configuration.configure().addClass(Cat.class);

//创建Session工厂对象

SessionFactory factory = configuration.buildSessionFactory();

//得到Session对象

Session session = factory.openSession();

//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

session.save(cat);

//如果取数据时候Animal父类接收的话,需要给出Anmail的全名

//提交事务

transaction.commit();

//关闭Session

session.close();

}

}

3ffe5396b16f1aa5676ac5b33c87026e.png

把所有子类映射成一张表

前面我们采用的是:每个子类都需要写成一个配置文件,映射成一张表…

如果子类的结构很简单,只比父类多几个属性。就像上面的例子…我们可以将所有的子类都映射成一张表中

但是呢,这样是不符合数据库设计规范的…..因为表中的数据可能是猫,可能是猴子…这明显是不合适的…

由于表中可能存在猫,存在猴子,为了区分是什么类型的。我们需要使用鉴别器

我们了解一下…

数据表

ed657aa09bf2af5d784ebcbc13f4bc36.png

实体

实体和上面雷同,只多了一个猴子的实体表

Monkey.java

public class Monkey extends Animal {

// 吃香蕉

private String eatBanana;

public String getEatBanana() {

return eatBanana;

}

public void setEatBanana(String eatBanana) {

this.eatBanana = eatBanana;

}

}

映射文件

使用了subClass这个节点和鉴别器

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

测试

加载的是Animal父类的映射文件。保存的是cat和monkey。

package zhongfucheng.aa;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

public class App5 {

public static void main(String[] args) {

//创建对象

Cat cat = new Cat();

Monkey monkey = new Monkey();

//设置属性

cat.setName("大花猫");

cat.setCatchMouse("小老鼠");

monkey.setEatBanana("吃香蕉");

monkey.setName("大猴子");

//获取加载配置管理类

Configuration configuration = new Configuration();

//加载Animal的映射文件!

configuration.configure().addClass(Animal.class);

//创建Session工厂对象

SessionFactory factory = configuration.buildSessionFactory();

//得到Session对象

Session session = factory.openSession();

//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

session.save(cat);

session.save(monkey);

//提交事务

transaction.commit();

//关闭Session

session.close();

}

}

51dc14dc05f1de0aba3ec0a2cb985a86.png

每个类映射一张表(3张表)

父类和子类都各对应一张表。那么就有三张表了

这种结构看起来是完全面向对象,但是表之间的结构会很复杂,插入一条子类的信息,需要两条SQL

数据表设计

f60cd4296aa741f522f14f3a2d9508e7.png

映射文件

使用到了这个节点

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

测试

package zhongfucheng.aa;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

public class App5 {

public static void main(String[] args) {

//创建对象

Cat cat = new Cat();

Monkey monkey = new Monkey();

//设置属性

cat.setName("大花猫");

cat.setCatchMouse("小老鼠");

monkey.setEatBanana("吃香蕉");

monkey.setName("大猴子");

//获取加载配置管理类

Configuration configuration = new Configuration();

//加载类对应的映射文件!

configuration.configure().addClass(Animal.class);

//创建Session工厂对象

SessionFactory factory = configuration.buildSessionFactory();

//得到Session对象

Session session = factory.openSession();

//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

session.save(cat);

session.save(monkey);

//提交事务

transaction.commit();

//关闭Session

session.close();

}

}

每保存一个子类对象需要两条SQL语句!

6d7856881391340f4e463e0d863ed39d.png

(推荐)每个子类映射一张表, 父类不对应表(2张表)

使用过了一张表保存所有子类的数据,这不符合数据库设计规范

每个子类、父类都拥有一张表..表结构太过于繁琐..添加信息时,过多的SQL

我们即将使用的是:每个子类映射成一张表,父类不对应表…这和我们传统方式继承是一样的。只不过在hbm.xml文件中使用了这个节点,由于有了这个节点,我们就不需要每个子类都写一个配置文件了。

数据库表设计

bbb8862240a366ef2211169ce88a6db4.png

映射文件

想要父类不映射成数据库表,只要在class中配置为abstract即可

使用了union-subclass节点,主键就不能采用自动增长策略了。我们改成UUID即可。当然啦,对应的实体id类型要改成String

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

测试

package zhongfucheng.aa;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

public class App5 {

public static void main(String[] args) {

//创建对象

Cat cat = new Cat();

Monkey monkey = new Monkey();

//设置属性

cat.setName("大花猫");

cat.setCatchMouse("小老鼠");

monkey.setEatBanana("吃香蕉");

monkey.setName("大猴子");

//获取加载配置管理类

Configuration configuration = new Configuration();

//加载类对应的映射文件!

configuration.configure().addClass(Animal.class);

//创建Session工厂对象

SessionFactory factory = configuration.buildSessionFactory();

//得到Session对象

Session session = factory.openSession();

//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

session.save(cat);

session.save(monkey);

//提交事务

transaction.commit();

//关闭Session

session.close();

}

}

c533f739c4870073f9bb862b31c9cce7.png

总结

由于我们的传统继承映射每个子类都对应一个配置文件,这样十分麻烦。因此.hbm.xml就给出了几个节点供我们使用,分别有以下的情况:

子类父类共有一张表subclass

不符合数据库设计规范

需要使用鉴别器

子类、父类都有自己的表joined-subclass,那么就是三张表

表的结构太过繁琐

插入数据时要生成SQL至少就要两条

子类拥有自己的表、父类不对应表【推荐】union-subclass

父类不对应表要使用abstract来修饰

主键的id不能使用自增长策略,修改成UUID就好了。对应的JavaBean的id设置成String就好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值