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

3 篇文章 0 订阅
2 篇文章 0 订阅
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();
}

//用完资源后需要关闭

/*释放资源:
Connection
Statement
ResultSet
1 尽量晚创建早释放
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

@Test
public 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();
    }
}

}

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

实现如下:

//测试查询单个值
@Test
public 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
 */
@Test
public 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的不同实现对象方法
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在上一篇文章中,我们介绍了JDBC中的PreparedStatement和ResultSet类的使用。在本文中,我们将介绍Apache Commons DbUtils库中的QueryRunner类。 QueryRunner类是Apache Commons DbUtils库中的一个类,它封装了大量的JDBC操作,简化了JDBC编程的复杂度。使用QueryRunner类可以避免编写大量的JDBC代码,提高开发效率。 使用QueryRunner类需要引入以下依赖: ```xml <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.7</version> </dependency> ``` 接下来我们来看一下如何使用QueryRunner类。 1. 建立连接 在使用QueryRunner类之前,需要先建立与数据库的连接。这可以通过JDBC中的DriverManager类来实现。例如: ```java Connection conn = DriverManager.getConnection(url, user, password); ``` 其中,url、user和password分别表示数据库的URL、用户名和密码。 2. 执行SQL语句 QueryRunner类中提供了多个方法来执行SQL语句。其中,最常用的方法是query()和update()方法。 query()方法用于查询数据,它的使用方式如下: ```java QueryRunner qr = new QueryRunner(); String sql = "SELECT * FROM user WHERE id=?"; Object[] params = {1}; ResultSetHandler<List<User>> rsh = new BeanListHandler<>(User.class); List<User> userList = qr.query(conn, sql, rsh, params); ``` 其中,第一个参数conn表示与数据库的连接,第二个参数sql表示要执行的SQL语句,第三个参数rsh表示查询结果的处理器,第四个参数params是一个数组,表示SQL语句中的参数。 update()方法用于更新数据,它的使用方式如下: ```java QueryRunner qr = new QueryRunner(); String sql = "UPDATE user SET name=? WHERE id=?"; Object[] params = {"张三", 1}; qr.update(conn, sql, params); ``` 其中,第一个参数conn表示与数据库的连接,第二个参数sql表示要执行的SQL语句,第三个参数params是一个数组,表示SQL语句中的参数。 3. 释放资源 在使用QueryRunner类完成数据库操作后,需要释放相应的资源,包括ResultSet、Statement和Connection等。这可以通过调用DbUtils类中的close()方法来实现。例如: ```java DbUtils.close(resultSet); DbUtils.close(statement); DbUtils.close(connection); ``` 4. 示例代码 下面是一个完整的示例代码,演示了如何使用QueryRunner类完成数据库操作: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; public class QueryRunnerDemo { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url, user, password); // 查询数据 QueryRunner qr = new QueryRunner(); String sql = "SELECT * FROM user WHERE id=?"; Object[] params = {1}; ResultSetHandler<List<User>> rsh = new BeanListHandler<>(User.class); List<User> userList = qr.query(conn, sql, rsh, params); for (User user : userList) { System.out.println(user); } // 更新数据 sql = "UPDATE user SET name=? WHERE id=?"; params = new Object[]{"张三", 1}; qr.update(conn, sql, params); conn.close(); } } ``` 以上就是QueryRunner类的使用方法。QueryRunner类封装了大量的JDBC操作,可以避免编写大量的JDBC代码,提高开发效率。同时,使用QueryRunner类也需要注意资源的释放,避免出现资源泄漏的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值