实现自己的JDBC框架

使用JDBC操作数据库时,dao层的增删改查有很多重复的代码,比如下面的

    public int getTotal() {
        Connection conn = null;//通用代码
        PreparedStatement ps = null;//通用代码
        ResultSet rs = null;//通用代码
        try {
            conn = ...//获取连接//通用代码
            ps = conn.prepareStatement("select count(*) from blog");//只有sql语句不同
            rs = ps.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                rs.close();//通用代码
                ps.close();//通用代码
                conn.close();//通用代码
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

如果做一个简单的增删改查,会发现很多代码都是通用的,如果重复使用无疑会让代码显得很冗余

如果使用框架开发,框架会帮我们省去这些麻烦,或者有很多开源的工具类也可以比如apache的DBUtil工具类

不过看了黑马的教学视频,感觉完全可以自定义一个JDBC框架来帮我们省去很多麻烦(虽然我是造轮子,不过学习初期造轮子还是很有帮助的)

自定义JDBC框架

对于增删改里面重复的代码最多,且不包含结果集(查询包含的结果集需要封装,所以单独定义),用update方法统一代表增删改,query方法代表查询

对于过程,我们发现用JDBC增删改查里面只有sql语句不一样,sql语句里的占位符又会不一样,所以考虑自定义方法里传入参数包含sql语句和sql语句中需要传入的参数(用数组表示),对于查询由于需要封装结果集到Bean中,但是Bean类实现不知道,所以无法直接封装,考虑使用策略模式

下面直接上代码,具体解释留在注释中

由于使用了DBCP数据源,所以用的DBCP数据源获取数据库连接,这里就不上DBCP的代码了

主类DBAssist

public class DBAssist {
    //设置连接从数据源获取
   //也可以不使用数据源,自己随便定义个Connection连接 
private DataSource ds; public DBAssist(DataSource ds){ this.ds=ds; } //增删改 public void update(String sql,Object[] params){ Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try{ conn=ds.getConnection();//得到链接 ps=conn.prepareStatement(sql); //设置参数, //ParameterMetaData方法获取参数信息 ParameterMetaData pmd=ps.getParameterMetaData(); //获取sql语句中的占位符?个数 int parameterCount=pmd.getParameterCount(); //获取的参数个数与传入的参数个数比较 if(parameterCount>0){ if(params==null||params.length<1) throw new IllegalArgumentException("the parameter is wrong"); if(params.length!=parameterCount) throw new IllegalArgumentException("the parameter is wrong"); for(int i=0;i<parameterCount;i++){ ps.setObject(i+1, params[i]); } } ps.executeUpdate(); }catch(Exception e){ throw new DBAssistException(e); }finally{ release(conn,ps,rs); } } //查询,由于不知道具体的Bean类,考虑使用策略模式 //ResultSetHandler为抽象出的策略接口,策略类需继承该类以完成封装 //策略类框架会给出实现 public Object query(String sql,Object[] params,ResultSetHandler rsh){ Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try{ conn=ds.getConnection(); ps=conn.prepareStatement(sql); ParameterMetaData pmd=ps.getParameterMetaData(); int parameterCount=pmd.getParameterCount();//sql语句中的占位符个数 if(parameterCount>0){ if(params==null||params.length<1) throw new IllegalArgumentException("the parameter is wrong"); if(params.length!=parameterCount) throw new IllegalArgumentException("the parameter is wrong"); for(int i=0;i<parameterCount;i++){ ps.setObject(i+1, params[i]); } } //得到查询结果集 rs=ps.executeQuery(); //封装结果集到对象中去,这里使用策略模式,最好提供实现类(类似于注册器) return rsh.handler(rs); }catch(Exception e){ throw new DBAssistException(e); }finally{ release(conn,ps,rs); } } //关闭连接 private void release(Connection conn,Statement stmt,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs=null; } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt=null; } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn=null; } } }

此时已经可以用update方法进行增删改的功能了

对于查询,query方法中的策略接口代码如下

public interface ResultSetHandler {
    public Object handler(ResultSet rs);
}

具体策略类有两个,分别用来查询单行和查询多行(利用反射填充Bean中的字段)

public class BeanHandler implements ResultSetHandler {
    private Class<? extends Object> clazz;

    public BeanListHandler(Class<? extends Object> clazz) {
        this.clazz = clazz;
    }

    public List<Object> handler(ResultSet rs) {
        try {
            List<Object> list = new ArrayList<Object>();
            while (rs.next()) {
                Object bean = clazz.newInstance();
          //查询数据库中的元数据信息 ResultSetMetaData rsmd
= rs.getMetaData(); int count = rsmd.getColumnCount(); for (int i = 0; i < count; i++) { String columnName = rsmd.getColumnName(i + 1); Object columnValue = rs.getObject(i + 1); Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(bean, columnValue); } list.add(bean); } return list; } catch (Exception e) { e.printStackTrace(); } return null; } }

 

//bean中字段名必须与数据库中字段名一致
public class BeanListHandler implements ResultSetHandler {
    private Class<? extends Object> clazz;
    public BeanHandler(Class<? extends Object> clazz) {
        this.clazz=clazz;
    }
    //查询单记录
    public Object handler(ResultSet rs) {
        try {
            Object bean=clazz.newInstance();
            if(rs.next()){
         ResultSetMetaData rsmd
=rs.getMetaData(); int count=rsmd.getColumnCount(); for(int i=0;i<count;i++){ String columnName=rsmd.getColumnName(i+1); Object columnValue=rs.getObject(i+1); Field field=clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(bean,columnValue); } return bean; } } catch (Exception e) { e.printStackTrace(); } return null; } }

Bean类

public class Blog {
    private int id;
    private int category_id;
    private String title;
    private String content;
    private Date created_time;
   ...
   //getter和setter方法
@Override public String toString() { return "Blog [id=" + id + ", category_id=" + category_id + ", title=" + title + ", content=" + content + ", created_time=" + created_time + "]"; } }

 

 

 

自定义异常类

public class DBAssistException extends RuntimeException {

    public DBAssistException() {
    }

    public DBAssistException(String message) {
        super(message);
    }

    public DBAssistException(Throwable cause) {
        super(cause);
    }

    public DBAssistException(String message, Throwable cause) {
        super(message, cause);
    }

    public DBAssistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

}

 最后测试下

  public void update(){
        String sql="update blog set created_time=? where id=?";
        dba.update(sql, new Object[]{new Date(System.currentTimeMillis()),1});
    }
   //查询单行记录测试
public void query(){ String sql="select * from blog"; Blog blog=(Blog) dba.query(sql, null,new BeanHandler(Blog.class)); System.out.println(blog.getTitle().length()); }
   //查询多行记录测试 @SuppressWarnings(
"unchecked") public List<Blog> query2(){ String sql="select * from blog"; List<Blog> list=(List<Blog>) dba.query(sql, null,new BeanListHandler(Blog.class)); return list; } public static void main(String args[]) { BlogDao test = new BlogDao();System.out.println(test.update()); test.query(); List<Blog> list=test.query2(); for(Blog l:list){ System.out.println(l); } } }

 

posted on 2016-08-30 21:26  pokid  阅读(393)  评论(0编辑  收藏  举报

导航