JDBC:提取重复代码进行重构

来源:互联网 发布:淘宝客返利在哪里查看 编辑:程序博客网 时间:2024/06/05 01:59

当我们在写 JDBC 代码连接数据库进行交互的时候,因为要写很多个增删改查的方法,有很多代码是重复的,而且这些代码必须但又不是主要业务,所以会造成代码的冗余,不利于后期的维护。所以我们必须把相同的代码抽取出来形成一个方法,在需要的时候直接调用这个方法就行了。那么在这中我们可以抽取四份不同的重复代码形成四个方法:

1. 数据库的连接

每次进行对数据库的增删改查,都需要先连接数据库,所以我们可以把连接数据库这部分代码抽取出来。

    public static Connection getConnection() {        Connection conn = null;        try {            //jdbc4 之后不再需要显式声明注册驱动,在调用getConnection()方法的时候,            //底层会通过url自动查找相应的驱动注册            //Class.forName("com.mysql.jdbc.Driver");            conn = DriverManager.getConnection(url,username,password);                                                                            } catch (SQLException e) {            e.printStackTrace();        }        return conn;    }

2.相应接口对象的关闭

在进行数据库连接进行增删改查的时候,通常会进行打开连接Connection,创建声明Statement,返回结果集ResultSet这样的操作,在使用完毕后通常是需要放在finally 中关闭的。这些写起来繁琐且重复的代码也需要被抽取出来。

    /**     * 只要是实现了AutoCloseable接口的实现类,都可以使用 此方法进行关闭     * @param auto     */    public static void close(AutoCloseable auto) {        if(auto != null) {            //判断是否关闭,未关闭则进行关闭            try {                auto.close();            } catch (Exception e) {                e.printStackTrace();            }        }    }

3. 增删改的抽取

在数据库增删改查这四种基本操作中,增删改这三种操作是可以不需要有返回值的,所以也可以抽取出来。

    /**     *      * @param sql    传入要进行执行的 sql 语句     * @param obj    可变参数,可以传入0-n个参数,使用Object类型可以传入任意类型的参数     */    public static void executeSQL(String sql,Object...obj) {        Connection conn = getConnection();            //获取数据库连接        PreparedStatement ps = null;        try {            ps = conn.prepareStatement(sql);        //预编译sql语句            for(int i = 0; i < obj.length; i++) {    //对预编译的sql语句中的占位符?进行传参                ps.setObject(i+1, obj[i]);            //占位符?从1开始,变参数组从0开始            }            ps.execute();                            //执行sql语句        } catch (SQLException e) {            e.printStackTrace();        }finally {            close(ps);                                //关闭接口对象            close(conn);        }    }

4.查询的抽取

增删改查这四种操作中,查询是有返回结果集的,所以要抽取相同代码形成一个通用方法是一件相对较麻烦的事情,但是重复的查询代码写多了也不利于维护,所以还是有必要抽取一下。

    /**     *      * @param sql    传入要执行的sql语句     * @param obj    可变参数,可以传入0-n个参数,使用Object类型可以传入任意类型的参数     * @return        返回一个List结果集     */    public static List<Map<String,Object>> executeQuery(String sql,Object...obj){        //声明一个List用来存储每一条记录,每一条记录相当于一个Map        //Map用来存储每条记录中的各字段的值,key:字段名;value:字段值        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();        Connection conn = getConnection();        //获取连接                    PreparedStatement ps = null;        ResultSet rs = null;        try {            ps = conn.prepareStatement(sql);        //预编译sql语句            for(int i = 0; i < obj.length; i++) {    //对预编译的sql语句中的占位符?进行传参                ps.setObject(i+1, obj[i]);            //占位符?从1开始,变参数组从0开始            }            rs = ps.executeQuery();                    //执行查询语句            ResultSetMetaData rsmd = rs.getMetaData();    //通过结果集获取对应的元数据            //遍历结果集            while(rs.next()) {                Map<String,Object> map = new HashMap<String,Object>();                //遍历获取的所有字段,把字段名和值存入map                for(int i = 1; i <= rsmd.getColumnCount(); i++) {                    map.put(rsmd.getColumnLabel(i), rs.getObject(i));                }                list.add(map);            //把每条记录map存入list            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            close(rs);                    //关闭接口对象            close(ps);            close(conn);        }        return list;    }

5.重构后

 通过重复代码的抽取形成通用方法之后,在进行对数据库的增删改查操作也变得简洁、更容易了:

public class PersonDaoImpl implements PersonDao {    @Override    public void insert(Person person) {        DBUtil.executeSQL("insert into person values(null,?,?,?,?)", person.getPersonname(),                person.getDegree(),person.getBirth(),person.getSal());    }    @Override    public void update(Person person) {        DBUtil.executeSQL("update person set personname=?,degree=?,birth=?,sal=? where personid=?", person.getPersonname(),                person.getDegree(),person.getBirth(),person.getSal(),person.getPersonid());    }    @Override    public void delete(int[] ids) {        for(int i = 0; i < ids.length; i++) {            DBUtil.executeSQL("delete from person where personid=?", ids[i]);        }    }    @Override    public List<Person> getAll() {        String sql = "select personid,personname,degree,birth,sal from person";        return this.convert(DBUtil.executeQuery(sql));    }    @Override    public List<Person> getPersonForPage(int pageSize, int pageOrder) {        String sql = "select personid,personname,degree,birth,sal from person limit ?,?";        return this.convert(DBUtil.executeQuery(sql,(pageOrder-1)*pageSize,pageSize));    }    @Override    public Person getPersonById(int id) {        String sql = "select personid,personname,degree,birth,sal from person where personid=?";        List<Person> list = this.convert(DBUtil.executeQuery(sql,id));        return list.isEmpty() ? null : list.get(0);    }    public List<Person> convert(List<Map<String,Object>> list){        List<Person> pList = new ArrayList<Person>();        for(Map<String,Object> map:list) {            Person p = new Person();            p.setPersonid((Integer)map.get("personid"));            p.setPersonname( map.get("personname").toString());            p.setDegree( map.get("degree").toString());            p.setBirth((Date) map.get("birth"));            p.setSal( (double) map.get("sal"));            pList.add(p);        }        return pList;    }}