第十二章 继承关系的映射

继承模型
在企业中经常会有员工的分类
我们在Java对象模型中可以使用继承的关系来实现,如下图:
[img]http://dl.iteye.com/upload/attachment/243906/4a95475b-97b2-314a-be63-058234da0d6f.bmp[/img]


 一张表映射
数据库中表的结构如下:


ID 姓名 地址 生日 开发人员技能 销售人员技能 员工类型
我们可以约定一种员工类型的规则,比如0普通员工,1开发人员,2销售人员

接下来,我们看一下Model层的实现和映射文件的编写:
Employee:
public class Employee {
protected String id;
protected String name;
protected String address;
protected Date birthday;

public Employee() {
super();
}

public Employee(String name, String address, Date birthday) {
super();
this.name = name;
this.address = address;
this.birthday = birthday;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}

Programmer:
public class Programmer extends Employee {
private String skill;

public Programmer(String name, String address, Date birthday, String skill) {
super(name, address, birthday);
this.skill = skill;
}

public Programmer() {
super();
}

public String getSkill() {
return skill;
}

public void setSkill(String skill) {
this.skill = skill;
}
}

Seller:
public class Seller extends Employee {
private String sell;

public Seller() {
super();
}

public Seller(String name, String address, Date birthday, String sell) {
super(name, address, birthday);
this.sell = sell;
}

public String getSell() {
return sell;
}

public void setSell(String sell) {
this.sell = sell;
}
}

映射文件:
<hibernate-mapping>
<class name="chapter5.model.Employee" table="employees"
discriminator-value="0">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<discriminator column="type" type="int" />
<property name="name" type="java.lang.String" column="name"
length="20" />
<property name="address" type="java.lang.String" column="address"
length="20" />
<property name="birthday" type="java.util.Date" column="birthday"
length="10" />
<subclass name="chapter5.model.Programmer" discriminator-value="1">
<property name="skill" type="java.lang.String" column="skill"
length="100" />
</subclass>
<subclass name="chapter5.model.Seller" discriminator-value="2">
<property name="sell" type="java.lang.String" column="sell"
length="100" />
</subclass>
</class>
</hibernate-mapping>
<discriminator column="type" type="int" />
鉴别器是给Hibernate来区分类型用的.就像listIndex是给list标签来记住元素顺序的作用是一样的,我们使用时不需要去理会这个字段,我们还是按我们平常的使用方式即可.

Dao层:
public class EmployeeDao {
public void create(Employee employee) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(employee);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}

public void delete(Employee employee) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.delete(employee);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}

public void update(Employee employee) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.update(employee);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}

public Employee findById(Serializable id) throws Exception {
Session session = null;
Employee employee = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
employee = (Employee) session.get(Employee.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return employee;
}
}
Test:
public class Test {
public static void main(String[] args) throws Exception {
EmployeeDao employeeDao = new EmployeeDao();

Employee employee = new Employee("张三", "武汉", new Date());
Programmer programmer = new Programmer("李四", "咸宁", new Date(),
"Java,sql,JS");
Seller seller = new Seller("李四", "襄樊", new Date(), "一流的销售技能");

employeeDao.create(employee);
employeeDao.create(programmer);
employeeDao.create(seller);
}
}
查找员工时应该注意要转型:
public class Test {
public static void main(String[] args) throws Exception {
EmployeeDao employeeDao = new EmployeeDao();
Employee employee = employeeDao
.findById("40285c8127d5f31b0127d5f31d4e0001");
System.out.println(employee.getName());
Programmer programmer = (Programmer) employeeDao
.findById("40285c8127d5f31b0127d5f31dbb0002");
System.out.println(programmer.getName() + ":" + programmer.getSkill());
Seller seller = (Seller) employeeDao
.findById("40285c8127d5f31b0127d5f31dcb0003");
System.out.println(seller.getName() + ":" + seller.getSell());
}
}

这种方法有个僻端:
可以看到数据库中,有很多空白的字段出现.
[img]http://dl.iteye.com/upload/attachment/243908/2ffcb731-0ab7-3049-8015-3bb4f6aabc6d.bmp[/img]

 解决方案:每个类映射到一张表
员工表:
ID 姓名 地址 生日

开发人员表
ID(主键,外键) 掌握的开发技能

销售人员表
ID(主键,外键) 掌握的销售技能

表之间的关系

[img]http://dl.iteye.com/upload/attachment/243910/9d56cb4f-7755-30f7-b2b3-5dae12a57f06.bmp[/img]


类模型不动,主要改动配置文件即可.
Dao层也不动,Test也不动
配置文件改动如下:
<hibernate-mapping>
<class name="chapter5.model.Employee" table="employees">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String" column="name"
length="20" />
<property name="address" type="java.lang.String" column="address"
length="20" />
<property name="birthday" type="java.util.Date" column="birthday" />
<joined-subclass name="chapter5.model.Programmer"
table="programmer">
<key column="id" />
<property name="skill" type="java.lang.String" column="skill"
length="100" />
</joined-subclass>
<joined-subclass name="chapter5.model.Seller" table="seller">
<key column="id" />
<property name="sell" type="java.lang.String" column="sell"
length="100" />
</joined-subclass>
</class>
</hibernate-mapping>
<key column="id" /> id在这里即是主键又是外键, 和一对一关系差不多, 指定的是子表的ID
再运行一下Test文件的增加代码,可以看到生成了三张表.
运行一下查询代码,可以看到,查询是多表联合查询,在查询效率上比一张表要复杂一些,但是在表结构上却合理的多.

 第三种解决方案
鉴别器与子表接合方案
比如开发人员表中只有一个字段,销售人员表中有多个字段,那么为开发人员单独加一张表有点浪费,可以将开发人员表与普通员工表二合一,只需要单独为销售人员增加一张表即可.

只需要改动配置文件即可:
[img]http://dl.iteye.com/upload/attachment/243912/21b6f646-88fa-3fa0-87c6-e1aa43a39f46.bmp[/img]

<hibernate-mapping>
<class name="chapter5.model.Employee" table="employees"
discriminator-value="0">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<discriminator column="type" type="int" />
<property name="name" type="java.lang.String" column="name"
length="20" />
<property name="address" type="java.lang.String" column="address"
length="20" />
<property name="birthday" type="java.util.Date" column="birthday" />
<subclass name="chapter5.model.Programmer"
discriminator-value="1">
<property name="skill" type="java.lang.String" column="skill"
length="100" />
</subclass>
<subclass name="chapter5.model.Seller" discriminator-value="2">
<join table="seller">
<key column="id" />
<property name="sell" type="java.lang.String" column="sell"
length="100" />
</join>
</subclass>
</class>
</hibernate-mapping>

 第四种解决方案:
每个类映射一张表
适用于公共字段较少的情况.
映射文件如下:
<hibernate-mapping>
<class name="chapter5.model.Employee" table="employees">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String" column="name"
length="20" />
<property name="address" type="java.lang.String" column="address"
length="20" />
<property name="birthday" type="java.util.Date" column="birthday" />

<union-subclass name="chapter5.model.Programmer" table="programmer">
<property name="skill" type="java.lang.String" column="skill"
length="100" />
</union-subclass>
<union-subclass name="chapter5.model.Seller" table="seller">
<property name="sell" type="java.lang.String" column="sell"
length="100" />
</union-subclass>
</class>
</hibernate-mapping>

以上就是解决继承的四种方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值