五、DAO组件的优化思路

一、问题引入

1、在上一节的增删改新闻内容代码中,代码段的不同之处在于sql语句以及由sql语句带来的?填充个数,在查中,根据查的字段的不同,最终的遍历也不同。
2、同时,要是我想对新闻类型表、新闻评论表进行增删改查呢?我要做好多小的重复的工作。
3、更换数据库的时候,sql语句有细微的区别,也需要大量的修改代码。
那有什么优化的方法吗?

二、优化思路

image.png

2.1提取公共操作

获取数据连接、释放资源、增删改、查。
将上面这四个数据库的公共操作提取出来,形成一个数据库操作的基类(就如同之前的XML公共操作类)。

2.2使用接口(接口是一种规范,只定义行为)

在第一条的基础上,这样在更换数据库的时候,只需要 引入相应的基类就好了。
针对新闻操作这个例子中,将NewsDao你去一个稳定的新闻操作的接口,新闻操作写在接口的实现类中。

三、提取公共操作

示例代码:

package cn.kgc.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//数据库操作基类
public class BaseDao {
    // 获取数据连接
    Connection connection = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    
    public boolean getConnection(){
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://127.0.0.1:3306/kgcnews?characterEncoding=utf-8";
            connection = DriverManager.getConnection(url, "root", "41312019");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    // 释放资源
    public boolean closeSource(){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
        }
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }
    
    // 增删改
    public int executeUpdate(String sql, Object[] params){
        int updateRows = 0;
        if (this.getConnection()) {
            try {
                pstmt = connection.prepareStatement(sql);
                // 填充占位符
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i+1, params[i]);
                }
                updateRows = pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return updateRows;
    }
    
    //查
    public ResultSet executeSQL(String sql, Object[] params){
        if (this.getConnection()) {
            try {
                pstmt = connection.prepareStatement(sql);
                // 填充占位符
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i+1, params[i]);
                }
                rs = pstmt.executeQuery();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return rs;
    }
}


注:
1、一定要注意释放资源的顺序。
2、在接受占位符的值得时候,用object数组,该数组的下标可以与值配合,有一个一一对应关系。
3、其实就这个项目来说,做到上面的提取公共操作就已经很简化了,但是既然是公共操作,就不可能把每个操作的结果详细描述出来,比如说我要进行增加新闻的操作,我调用了父类的方法,有结果之后只能显示改变成功,不能显示“增加新闻成功”,如果要显示增加新闻成功,我需要用一个子类继承这个公共类,然后在子类中调用这个公共操作,拿到结果了之后再去显示“增加新闻成功”。

四、定义接口

接口的意义在于定义一种规范,我只要实现了这个接口,我就必须实现接口里面定义的各种方法。
就这个新闻管理系统来说,虽然只要做到提取公共操作这一步我就很简化了,但是我还是需要使用接口来保证规范性。
最终的修改如下:
接口代码:

package cn.kgc.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;

public interface NewsDao {
    // 增加新闻信息
    public void addNews(int id,int categoryId,String title,String summary,String content,String author,Date createDate);
    // 删除特定新闻
    public void deleteNews(int id);
    // 修改特定新闻的标题
    public void updateNews(int id, String title);
    // 查询全部新闻信息
    public void getAllNews();
    // 查询特定的新闻id、标题
    public void getNewsByTitle(String title);
}

公共操作类的代码见第三步。
最终的子类代码如下:

package cn.kgc.dao.implement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;

import cn.kgc.dao.BaseDao;
import cn.kgc.dao.NewsDao;

// 使用PreparedStatement
public class NewsDaoImpl extends BaseDao implements NewsDao {

    // 增加新闻信息
    public void addNews(int id,int categoryId,String title,String summary,String content,String author,Date createDate){
        String sql = "INSERT INTO news_detail(id, categoryId, title, " +
                "summary,content,author, createDate) VALUES(?,?,?,?,?,?,?);";
        Object[] params = {id, categoryId, title, summary,content, author,createDate};
        int i = this.executeUpdate(sql, params);
        if (i > 0) {
            System.out.println("插入资源成功!");
        }
        this.closeSource();
    }
    // 删除特定新闻
    public void deleteNews(int id){
        String sql = "DELETE FROM news_detail WHERE id=?";
        Object[] params = {id};
        int i = this.executeUpdate(sql, params);
        if (i > 0){
            System.out.println("删除新闻信息成功");
        }
        this.closeSource();
    }
    // 修改特定新闻的标题
    public void updateNews(int id, String title){
        String sql = "UPDATE news_detail SET title=? WHERE id=?";
        Object[] params = {title,id};
        int i = this.executeUpdate(sql, params);
        if (i > 0){
            System.out.println("修改新闻信息成功");
        }
        this.closeSource();
    }
    // 查询全部新闻信息
    public void getAllNews(){
        String sql = "SELECT id, title, author,createDate FROM news_detail";
        Object[] params = {};
        ResultSet rs = this.executeSQL(sql,params);
        try {
            while(rs.next()){
                int id = rs.getInt("id");
                String newsTitle = rs.getString("title");
                String author = rs.getString("author");
                Timestamp createdate = rs.getTimestamp("createDate");
                System.out.println(id + " " + newsTitle + " " + author + " " + createdate);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        this.closeSource();
    }
    
    // 查询特定的新闻id、标题
    public void getNewsByTitle(String title){
        try {
            String sql = "SELECT id, title FROM news_detail where title=?";
            Object[] params = {title};
            ResultSet rs = this.executeSQL(sql,params);
            while(rs.next()){
                int id = rs.getInt("id");
                String newsTitle = rs.getString("title");
                System.out.println(id + " " + newsTitle);
            }
        }catch (SQLException e) {
            e.printStackTrace();
        } finally {
            this.closeSource();
        }
    }
    
    public static void main(String[] args) {
        NewsDao dao = new NewsDaoImpl();
        dao.getAllNews();
    }
}

在最终的子类中,我即继承了接口,来保证我代码的规范性,又继承了父类,来使得我的最终代码里面不重复,足够的简洁。这才是一个优秀的程序员应该写的代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,368评论 25 709
  • 太多的人,说自己不喜欢、不羡慕别人闪亮的生活,不是因为他们将自己的生活过得风生水起、过出了心里的最佳样子,只是因为...
    家以纯阅读 4,140评论 4 6
  • gulp glob:用来匹配文件路径的,不同语言下有不同的规则。【node-glob】
    shanshanfei阅读 876评论 0 0
  • 我是去年5月底报名学车,那时工作比较稳定,周末闲着没事,就想报个驾校,拿到驾照。问了身边的很多同事朋友,都没有特别...
    浏如阅读 2,662评论 2 1
  • 慢,有时就是快 跑马拉松有一段时间了。从某个特别的契机接触到跑马拉松的分享,到自己真正跑在马拉松的赛道上,并没有刻...
    Lufeewang阅读 4,793评论 1 2

友情链接更多精彩内容