Hibernate框架的搭建
分层体系结构与持久化
三层体系结构
分层体系结构
指的是将系统的组件分隔到不同的层中,每一层中的组件应保持内聚性; 每一层都应与它下面的各层保持松散耦合。
层与层之间存在自上而下的依赖关系,即上层组件会访问下层组件的API,而下层组件不应该依赖上层组件。
每个层对上层公开API,但具体的实现细节对外透明。当某一层的实现发生变化,只要它的API不变,不会影响其他层的实现。
持久化层是怎么来的
为了把数据访问细节和业务逻辑分开,可以把数据访问作为单独的持久化层。
什么是持久化
瞬时状态:保存在内存的程序数据,程序退出后,数据就消失了,称为瞬时状态。
持久状态:保存在数据库(磁盘)的程序数据,程序退出后,数据依然存在,称为程序数据的持久状态。
持久化:将程序数据在瞬时状态和持久化状态之间转换的机制。
持久化层的作用
持久化层封装了数据访问细节,为业务逻辑层提供面向对象的API,使业务逻辑层可以专注于实现业务逻辑。
MVC设计模式与四层结构的对应关系
持久化层设计目标
持久化层的设计目标:
代码可重用性高,能够完成对象持久化操作;
如果需要的话,能够支持多种数据库平台;
具有相对独立性,当持久层发生变化时,不会影响上层实现。
Hibernate是持久化层框架。
软件的模型及ORM
软件的模型
在软件开发的不同阶段,需要为目标系统创建不同类型的模型:
在分析阶段,需要创建概念模型;
在设计阶段,需要创建域模型和数据模型。
概念模型
概念模型用来模拟问题域中的真实实体。
概念模型描述了每个实体的概念和属性,以及实体之间的关系。
概念模型并不描述实体的行为。
关系数据模型
关系数据模型是在概念模型的基础上建立起来的,用于描述这些关系数据的静态结构,它由以下内容组成:
一个或多个表;
表与表之间的参照完整性;
表的所有索引;
触发器;
视图。
域模型
域模型是面向对象的,在面向对象术语中,域模型也可称为设计模型。
域模型由以下内容组成:
具有状态和行为的域对象;
域对象之间的关系。
域对象
域对象可以代表业务领域中的人、地点、事物或概念等。
域对象分为以下几种:
实体域对象:业务领域的名词;
过程域对象:业务领域的动词;
事件域对象:业务领域中的事件。
域对象关联关系
从Order到Customer的多对一单向关联。
从Customer到Order的一对多单向关联。
从Customer到Order的一对多双向关联。
对象-关系映射
一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录。
域模型与关系模型之间存在许多不匹配之处
域模型中有继承关系,关系模型不能直接表示继承关系。
域模型中有多对多关联关系,关系模型通过连接表来表示多对多关联关系。
域模型中有双向关联关系,关系模型只有单向参照关系,而且总是many方参照one方。
域模型提倡精粒度模型,而关系模型提倡粗粒度模型。
对象-关系映射
对象-关系映射(Object Relational Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。用来把域模型表示的对象映射到关系数据模型对应的数据库结构中去。
通过ORM模式在操作实体对象的时候,就不需要再去和复杂的 SQL语句打交道,只需简单的操作实体对象的属性和方法,ORM 技术是在对象和关系之间提供了一条桥梁,对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化。
ORM框架
通过ORM框架实现
通过JDBC实现
直接通过JDBC API来持久化实体域对象。
public interface CustomerManger {
public void saveCustomer(Customer customer);
public void deleteCustomer(Customer customer);
public void updateCustomer(Customer customer);
public Customer loadCustomer(long id);
public List findCustomerByName(String name);
public List findCustomerByAge(int age);
public List findCustomerByNameAndAge(String name,
int age);
public List findCustomer(String sqlstr);
}
通过JDBC实现的缺点
业务逻辑和关系数据绑定,如果关系数据模型发生变化,例如修改了表的结构,那么必须手工修改程序代码中所有相关的SQL语句,增加了软件维护的难度。
如果程序代码中的SQL语句包含语法错误,在编译时不能检查这种错误,在运行时才能发现这种错误,这增加了调试程序的难度。
持久化层产生大量冗余代码,如下3个查询方法,程序代码都很相似,仅仅是 SQL SELECT 语句中的查询条件不一样。
public List findCustomerByName(String name);
public List findCustomerByAge(int age);
public List findCustomerByNameAndAge(String name, int age);
findCustomer()方法是供业务逻辑层调用,使得业务逻辑层需要了解数据库的访问细节,无法达到软件分层的效果。