JDBC QueryRunner(开源框架)之查询 详解

来源:互联网 发布:安德罗妮淘宝 编辑:程序博客网 时间:2024/05/22 14:52

QueryRunner查询数据库& QueryRunner如何封装起来的

一、简单描述JDBC获取连接Connection后能做什么?

首先 查看相关API

(一).使用类和方法

  • QueryRunner(接口的方法如下两个):
  • update(connection,sql,object…objs) //进行增删改方法
  • query(connection,sql,ResultSetHandler,object…objs)//查询方法

    • ResultSetHandler接口
  • 常用实现类:
  • BeanHandler 封装一个实体对象
  • BeanListHandler 封装 一组多个实体对象到list
  • ScalarHandler 获取单个值
  • MapListHanlder 封装 一组map到list

(二)在详细的解析了JDBC使用C3P0 或 DBCP获取了连接Connection 之后

进一步的需要对数据库进行数据的增删改查一系列的操作

其中大多数操作(其实可以封装在DAO里)不外乎(操作这些共同的方法)

public interface DAO<T> { /*  一、批量处理的方法 * * @param connection:  数据库连接 * @param sql:  SQL语句 * @param args:  填充占位符的Object []类型的可变参数 */void batch(Connection connection,String sql,Object[] ...args);/*   二、返回具体的一个值  如  平均成绩  总数 *  * @param connection:  数据库连接 * @param sql:  SQL语句 * @param args:  填充占位符的可变参数 */<E> E getForValue(Connection connection,String sql,Object ...args);/*   三、返回一个T的一个集合相当于查询所有记录 *  * @param connection:  数据库连接 * @param sql:  SQL语句 * @param args:  填充占位符的可变参数 */List<T> getForList(Connection connection,String sql,Object ...args);/*   四、返回一个T的对象 *  * @param connection:  数据库连接 * @param sql:  SQL语句 * @param args:  填充占位符的可变参数 */T get(Connection connection,String sql,Object ...args) throws SQLException;/*  五、增删改操作 * * INSERT UPDATE DELETE * @param connection:  数据库连接 * @param sql:  SQL语句 * @param args:  填充占位符的可变参数 */    void update(Connection connection,String sql,Object ...args) throws SQLException;}

二、此文主要解析使用框架QueryRunner 进行 ★查询qruery()操作

//正如我们平时使用最流行的 方法进行操作 不多说 上代码

<1>首先导入jar包(驱动和连接池的不算)

commons-dbutils-1.3.jar

<2>封装使用C3P0获取连接和关闭连接 这两个方法封装如下:

public class JDBCUtils {//数据库连接池值应该被初始化一次放在静态代码块中private static DataSource datasource=null;static{    datasource =new ComboPooledDataSource("helloc3p0");}public static  Connection getConnection() throws SQLException{    return datasource.getConnection();}//用完资源后需要关闭/*释放资源:ConnectionStatementResultSet1 尽量晚创建早释放2 后使用的先关闭*/public static void release(ResultSet rs,Statement statement,Connection conn){     if(rs!=null){            try{                rs.close();            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }      if(statement!=null){    try{        statement.close();    } catch (Exception e) {        // TODO Auto-generated catch block        e.printStackTrace();    }}       if(conn!=null){        try {            conn.close();        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();    }  }}

<3>步创建QueryRunner 实例对象 调用query()方法

例一、以最复杂查询所有对象的键值对为例如下:

//分析所有对象的键值对 ①键值对需要放在Map集合中 多个对象需要放在集合中 所以如下

//不同的查询方法只是返回结果需要实现的ResultSetHandler接口对象不同

//测试查询List

@Testpublic void testMapList() throws Exception{    Connection conn =JDBCUtils.getConnection();    //创建QueryRunner对象    QueryRunner qr = new QueryRunner();    //调用方法其query查询方法    try{    //下面需要根据查询方法创建ResultSetHandler对象    //将结果集中的每一行数据都封装到一个Map里,然后再存放到List     List<Map<String, Object>> query = qr.query(conn, "select * from      表名 where 字段名=?", new MapListHandler(),"女");    }catch (Exception e){     System.out(e.getMasage());    }finally{   //关闭资源          JDBCUtils.release(conn, null, null);    }    //此处作测试直接遍历Map打印 否则返回     for (Map<String, Object> map : query) {         Set<Entry<String, Object>> entrys = map.entrySet();         Iterator<Entry<String, Object>> iterator = entrys.iterator();        while (iterator.hasNext()) {            Map.Entry<String, Object> entry = iterator.next();            String key = entry.getKey();            Object value = entry.getValue();            System.out.print(key+"\t"+value+" |||| ");        }        System.out.println();    }}

}

例二、查询返回某个值如(总数和 或 平均分)

实现如下:

//测试查询单个值@Testpublic void testScalar() throws Exception{    Connection conn =JDBCUtils.getConnection(); //创建QueryRunner对象 QueryRunner qr = new QueryRunner();    //调用方法    Object query = qr.query(conn, "select count(*) from student",  new ScalarHandler());   //此处测试直接打印(实际应用中返回结果)    System.out.println(query);    //关闭连接    JDBCUtils.release(conn, null, null);}

三、在没有使用QueryRunner 框架之前是如何实现的呢?

使用的操作实现类有两个是prepareStatement和Statement

使用的结果处理有ResultSetMetaData实现类获取结果对象的对应值

★★那么prepareStatement和Statement它们有什么区别呢???

第一:

prepareStatement会先初始化SQL先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

第二:

prepareStatement可以替换变量在SQL语句中可以包含?,可以用ps=conn.prepareStatement("select* from Cust where ID=?");int sid=1001;ps.setInt(1, sid);rs = ps.executeQuery();可以把?替换成变量。而Statement只能用int sid=1001;Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("select * from Cust where ID="+sid);来实现。

第三:

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

例一:

使用方式一:获取对象为statement进行查询单个对象如下

 /**一、使用statement测试查询单个对象 *  * @throws Exception */@Testpublic void testQuery() throws Exception{    Connection connection =JDBCUtils.getConnection();    //获取执行命令对象    Statement statement = connection.createStatement();    //执行★     ResultSet set = statement.executeQuery("select sex,name from 表名");       while(set.next()){    //   Object id = set.getObject(1);//得到第一列         Object name = set.getObject(2);//得到第2列         Object sex = set.getObject(1);//得到第3列   //    Object email = set.getObject(4);//得到第4列   //    Object borndate = set.getObject(5);//得到第5列         //输出一个就行测试         System.out.println(name+"\t"+sex);     }    //释放资源     JDBCUtils.release(set, statement,connection);    }}

例二:

使用方式二:使用PreparedStatement 的对象prepareStatement 改进方式一

查询所有对象如:

public List<T> query(Class<T> clazz, String sql, Object... objects) {Connection connection = null;PreparedStatement statement = null;ResultSet set = null;    List<T> list=new ArrayList<>();    try {            //1.获取连接            connection = JDBCUtils.getConnection();        //2.获取PreparedStatement对象prepareStatement            statement = connection.prepareStatement(sql);            //为sql占位符 赋值            for (int i = 0; i < objects.length; i++) {                statement.setObject(i+1, objects[i]);            }            //3.执行sql 进行executeQuery()查询操作并处理结果             set= statement.executeQuery();             //创建ResultSetMetaData对象获取查询结果的对象对应值             ResultSetMetaData metaData = set.getMetaData();             while(set.next()){             //通过反射创建对象            T t  = clazz.newInstance();//实体类必须有无参构造         //遍历结果集         for (int i = 0; i < metaData.getColumnCount(); i++) {         //得到列名         String name = metaData.getColumnLabel(i+1);        //得到列对应的值         Object value = set.getObject(name);        //通过反射设置属性        Field field = clazz.getDeclaredField(name);        //利用反射对private私有属性进行暴力破解        field.setAccessible(true);        //调用封装的实体类中的set()方法给属性赋值                 field.set(t, value);                }       // 将对象放入ArrayList集合中                 list.add(t);//将t添加到list             }       //返回最终结果            return list;        } catch (Exception e) {            throw new RuntimeException(e.getMessage());        }finally{        //关闭连接            JDBCUtils.release(connection, statement, set);        }}

四、分析总结

在使用QueryRunner 之前我们的操作对象有两个

1.prepareStatement和Statement调用其方法:           execute()进行查询 相当于    QueryRunner的query()方法           executeUpdate()进行增删改 相当于 QueryRunner的update()方法2、使用apache下的PropertyUtils将对象赋予查询的结果     import org.apache.commons.beanutils.PropertyUtils;   PropertyUtils.setProperty(t, name, value);2.处理结果方法有ResultSetMetaData的对象    调用其方法:           metaData.getColumnCount()获取结果集长度           //获取其列名或别名           String name = metaData.getColumnLabel(i+1);         //获取其列名或别名对应的值           Object value = set.getObject(name);         //将获取值放入对象中          PropertyUtils.setProperty(t, name, value);   相当于相当于 QueryRunner的ResultSetHandler的不同实现对象方法
0 0
原创粉丝点击