首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

第十二章 沿袭关系的映射

2012-10-21 
第十二章 继承关系的映射继承模型 在企业中经常会有员工的分类我们在Java对象模型中可以使用继承的关系来

第十二章 继承关系的映射
继承模型
在企业中经常会有员工的分类
我们在Java对象模型中可以使用继承的关系来实现,如下图:



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


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 />
</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());
}
}

这种方法有个僻端:
可以看到数据库中,有很多空白的字段出现.


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

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

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

表之间的关系




类模型不动,主要改动配置文件即可.
Dao层也不动,Test也不动
配置文件改动如下:
<hibernate-mapping>
<class name="chapter5.model.Employee" table="employees">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator />
</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文件的增加代码,可以看到生成了三张表.
运行一下查询代码,可以看到,查询是多表联合查询,在查询效率上比一张表要复杂一些,但是在表结构上却合理的多.

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

只需要改动配置文件即可:


<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 />
</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 />
</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>

以上就是解决继承的四种方案

热点排行