DAO模式介绍
DAO是Data Access Object(数据访问对象)的简称。
首先,你的应用程序肯定会有业务逻辑的代码。在三层架构的web系统中,业务逻辑的代码,就是在你的Service组件里面;在我们的spark作业中,业务逻辑代码就是在我们的spark作业里面。
如果说,不用DAO模式的话,那么所有的数据库访问的代码和逻辑会全部耦合在业务逻辑代码里面。比如,你的业务逻辑代码中,可能会充斥着JDBCHelper,定义SQL语句,处理查询返回结果等等代码。会导致业务逻辑和数据访问严重耦合。导致以后如果你只是想修改数据访问的代码,那么还得在一大堆业务逻辑的代码中去找,找到这段代码,然后去做对应的修改。
因此我们要将数据库访问的代码,封装在DAO中,然后业务逻辑的代码,就可以直接去调用DAO组件,实现数据库操作的逻辑。如果这样做了以后,那么在业务逻辑的代码中,就不可能出现SQL语句、查询结果处理等等这些东西。当后面对系统进行维护的时候,如果你只是要优化一条SQL语句,那么你肯定不用跑到业务逻辑的代码里面去找到这条SQL语句,然后去修改它。 只需要到业务逻辑代码调用的DAO组件里面去,找到对应的SQL语句修改即可。
引入了DAO模式以后,就大大降低了业务逻辑层和数据访问层的耦合,大大提升了后期的系统维护的效率,并降低了时间成本。
我们自己在实现DAO模式的时候,通常来说,会将其分为两部分,一个是DAO接口;一个是DAO实现类。我们的业务的代码,通常就是面向接口进行编程;那么当接口的实现需要改变的时候,直接定义一个新的实现即可。但是对于我们的业务代码来说,只要面向接口开发就可以了。DAO的改动对业务代码应该没有任何的影响。
domain概念介绍
在系统中,通常会分很多层,比如经典的三层架构:控制层、业务层、数据访问层(DAO层)
此外,还有一个层,就是domain层。domain层,通常就是用于放置这个系统中,与数据库中的表,一一对应起来的JavaBean。
创建domain任务类
import java.io.Serializable; /** * 任务 * @author chenc * */ public class Task implements Serializable{ //尽量让domain实现Serializable private static final long serialVersionUID = 3518776796426921776L; private long taskid; private String taskName; private String createTime; private String startTime; private String finishTime; private String taskType; private String taskStatus; private String taskParam; // shift+alt+s public long getTaskid() { return taskid; } public void setTaskid(long taskid) { this.taskid = taskid; } public String getTaskName() { return taskName; } public void setTaskName(String taskName) { this.taskName = taskName; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getStartTime() { return startTime; } public void setStartTime(String startTime) { this.startTime = startTime; } public String getFinishTime() { return finishTime; } public void setFinishTime(String finishTime) { this.finishTime = finishTime; } public String getTaskType() { return taskType; } public void setTaskType(String taskType) { this.taskType = taskType; } public String getTaskStatus() { return taskStatus; } public void setTaskStatus(String taskStatus) { this.taskStatus = taskStatus; } public String getTaskParam() { return taskParam; } public void setTaskParam(String taskParam) { this.taskParam = taskParam; } }
创建任务管理DAO接口
/** * 任务管理DAO接口:降低数据访问层与业务逻辑层的耦合 * @author chenc * */ public interface ITaskDAO { /** * 根据主键查询任务 * @param taskid * @return */ Task findById(long taskid); }
创建任务管理DAO实现类
/** * 任务管理DAO实现类 * @author chenc * */ public class TaskDAOImpl implements ITaskDAO{ public Task findById(long taskid) { final Task task = new Task(); String sql = " select * from task where task_id = ?"; Object[] params = new Object[] {taskid}; //获取单例 JDBCHelper jdbcHelper = JDBCHelper.getInstance(); jdbcHelper.executeQuery(sql, params, new JDBCHelper.QueryCallback() { @Override public void process(ResultSet rs) throws Exception { if(rs.next()) { long taskid = rs.getLong(1); String taskName = rs.getString(2); String createTime = rs.getString(3); String startTime = rs.getString(4); String finishTime = rs.getString(5); String taskType = rs.getString(6); String taskStatus = rs.getString(7); String taskParam = rs.getString(8); task.setTaskid(taskid); task.setTaskName(taskName); task.setCreateTime(createTime); task.setStartTime(startTime); task.setFinishTime(finishTime); task.setTaskType(taskType); task.setTaskStatus(taskStatus); task.setTaskParam(taskParam); } } }); return task; } }
工厂模式
如果没有工厂模式,可能会出现的问题:
ITaskDAO接口和TaskDAOImpl实现类;实现类是可能会更换的;那么,如果你就使用普通的方式来创建DAO,比如ITaskDAO taskDAO = new TaskDAOImpl(),那么后续,如果你的TaskDAO的实现类变更了,那么你就必须在你的程序中,所有出现过TaskDAOImpl的地方,去更换掉这个实现类。这是非常非常麻烦的。如果说,你的TaskDAOImpl这个类,在你的程序中出现了100次,那么你就需要修改100个地方。这对程序的维护是一场灾难。
对于一些种类的对象,使用一个工厂,来提供这些对象创建的方式,外界要使用某个类型的对象时,就直接通过工厂来获取即可。不用自己手动一个一个地方的去创建对应的对象。
那么,假使我们有100个地方用到了TaskDAOImpl。不需要去在100个地方都创建TaskDAOImpl()对象,只要在100个地方,都使用TaskFactory.getTaskDAO()方法,获取出来ITaskDAO接口类型的对象即可。如果后面,比如说MySQL迁移到Oracle,我们重新开发了一套TaskDAOImpl实现类,那么就直接在工厂方法中,更换掉这个类即可。不需要再所有使用到的地方都去修改。
/** * DAO工厂类 * @author chenc * */ public class DAOFactory { /** * 获取任务管理DAO * @return DAO */ public static ITaskDAO getTaskDAO() { return new TaskDAOImpl(); } }
TEST
public class TaskDAOTest { public static void main(String[] args) { ITaskDAO taskDAO = DAOFactory.getTaskDAO(); Task task = taskDAO.findById(1); System.out.println(task.getTaskName()); } }
返回“测试任务001 ”即为正确。此返回值是在TASK 表中插入的task_id为1 的数据的TaskName