导读:
本篇是JAVA基础系列的第22篇,今天我们梳理DAO模式开发及分层的相关知识。
1.分层开发
分层开发是一种化大为小,分而治之的软件开发方法。
分层开发的好处:
-
各层专注于自己功能的实现,便于提高质量
-
便于分工协作,提高开发效率
-
便于代码复用
-
便于程序扩展
分层开发的原则
-
封装性原则 每个层次向外公开接口,但是隐藏内部细节
-
顺序访问原则 下一层为上一层服务,但不使用上层的服务
在项目实际开发过程中,通常会将整个项目从上到下划分为表现层、业务层、持久层(数据访问层)。也就是常说的三层架构。
三层架构在我们的实际开发中使用的非常多。我们接下来看看每层都负责哪些方面:
-
表现层
:也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协 议请求 web 层,web 需要接收 http 请求,完成 http 响应。表现层包括展示层和控制层:控制层负责接 收请求,展示层负责结果的展示。表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系) -
业务层
:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业 务层,但是业务层不依赖 web 层。业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制) -
持久层
:也就是我们常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进 行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进行增删改查的。
三层架构的目的着重点是”高内聚,低耦合”,也就是解耦。
2.持久化
数据访问层在学习过程中必须了解什么是持久化。在程序中数据的状态有两种,第一种是瞬时状态,第二种是持久状态。而持久化指的是将程序中的数据在瞬时状态和持久状态间转换的机制。
瞬时状态数据:例如我们在运行过程中声明的变量,对应的数据保存在内存之中,程序结束后就会销毁
持久状态数据:指的是保存在数据库、文本文件、xml文件之中的数据。
持久化的主要操作:读取、保存、修改、删除、查询
3.DAO模式
DAO (DataAccessobjects 数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作都封装起来。对外提供相应的接口。
DAO 模式提供了访问关系型数据库系统所需操作的接口,将数据访问和业务逻辑分离对上层提供面向对象的数据访问接口。
DAO 模式的优势就在于它实现了两次隔离。
-
隔离了数据访问代码和业务逻辑代码。业务逻辑代码直接调用DAO方法即可,完全感觉不到数据库表的存在。分工明确,数据访问层代码变化不影响业务逻辑代码,这符合单一职能原则,降低了耦合性,提高了可复用性。
-
隔离了不同数据库实现。采用面向接口编程,如果底层数据库变化,如由 MySQL 变成 Oracle 只要增加 DAO 接口的新实现类即可,原有 MySQL 实现不用修改。这符合 “开-闭” 原则。该原则降低了代码的耦合性,提高了代码扩展性和系统的可移植性。
4.DAO 模式组成
一个典型的DAO 模式主要由以下几部分组成。
-
DAO接口:把对数据库的所有操作定义成抽象方法,可以提供多种实现。
-
DAO 实现类:针对不同数据库给出DAO接口定义方法的具体实现。
-
实体类(JavaBean类):用于在层与层之间进行存放与传输对象数据。
-
数据库连接和关闭工具类:避免了数据库连接和关闭代码的重复使用,方便修改。
数据库连接和关闭工具类
public class BaseDao { private static final String DRIVER_NAME = "com.mysql.jdbc.Driver";// 数据库驱动字符串 private static final String URL = "jdbc:mysql://localhost:3306/demo";// 连接URL字符串 private static final String USER_NAME = "root"; // 数据库用户名 private static final String PWD = "root"; // 用户密码 /** * 获取数据库连接对象。 */ public Connection getConnection() { Connection conn = null;// 数据连接对象 // 获取连接并捕获异常 try { Class.forName(DRIVER_NAME); conn = DriverManager.getConnection(URL, USER_NAME, PWD); } catch (Exception e) { e.printStackTrace();// 异常处理 } return conn;// 返回连接对象 } /** * 关闭数据库连接。 * @param conn 数据库连接 * @param stmt Statement对象 * @param rs 结果集 */ public void closeAll(Connection conn, Statement stmt, ResultSet rs) { // 若结果集对象不为空,则关闭 if (rs != null) { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } } // 若Statement对象不为空,则关闭 if (stmt != null) { try { stmt.close(); } catch (Exception e) { e.printStackTrace(); } } // 若数据库连接对象不为空,则关闭 if (conn != null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } } }
DAO接口
public interface UserDao { /** * 查询所有用户 */ List<User> findUsers() throws Exception; //省略其他方法 }
DAO 实现类
public class UserDaoImpl extends BaseDao implements UserDao { /** * 查询所有用户 */ public List<User> findUsers() throws Exception { Connection conn = super.getConnection(); String sql="select * from user"; PreparedStatement stmt= conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); List<User> userList=new ArrayList<User>(); while(rs.next()) { User user = new User( rs.getInt("id"), rs.getString("userName"), rs.getString("password"), rs.getString("info"), rs.getInt("sex") ); userList.add(user); } super.closeAll(conn, stmt, rs); return petList; } }
实体类(JavaBean类)
public class User { private Integer id; private Integer userName; private Integer password; private String info; private int sex; //省略构造方法和get\set方法 }
5.DAO模式分层开发的优缺点
通过上方代码可以看出,使用DAO模式进行开发,各有优缺点
优点:
-
数据存储逻辑的分离:一方面避免业务代码中混杂的JDBC代码,另一方面,数据访问接口与数据访问实现相分离,这样精通数据库的人可以根据接口专注于数据库访问的最优化实现,而精通业务的人可以专注于业务逻辑编码
-
数据访问底层实现的分离:DAO模式将数据访问分为抽象层和实现层,分离了数据使用和数据访问的底层实现细节。这样可以在保持上层结构不变的情况下,通过更改底层实现来修改数据访问的机制,比如只要通过修改数据访问层实现,我们就可以部署在不同数据库平台上
-
资源管理和调度的分离:数据访问逻辑从业务逻辑中脱离开来,使数据访问层实现统一的资源调度,通过数据库连接池和各种缓存机制的使用,可以保持上层系统不变的情况下来提高系统性能
-
数据抽象:通过对底层数据的封装,开发人员可以使用面向对象思想对数据进行操作。比如通过调用方法获取数据比通过SQL语句访问数据库获取数据,在代码上更易于理解,清晰,对日后维护带来便利
缺点:
-
增加了程序代码的复杂性,增加了多余的层。
-
对于新手程序猿来说,不易理解,尤其是层与层之间调用时