使用JDBC方式连接ClickHouse查询数据

日常开发中,对于操作ClickHouse中的数据,查询是最常用的功能。本文通过代码示例介绍使用JDBC方式连接ClickHouse查询数据的两种接口:Statement 和 PreparedStatement接口。

1. 引入ClickHouse驱动依赖包

笔者使用idea开发工程,首先创建maven项目,POM文件引入ClickHouse驱动依赖包。

ru.yandex.clickhouseclickhouse-jdbc0.2.4

2. 编写应用程序代码查询ClickHouse数据

JDBC连接ClickHouse的两种接口主要区别是:Statement 接口不接受参数,PreparedStatement 接口运行时接受输入的参数。

2.1 Statement接口

Statement可以正常访问数据库,适用于运行静态 SQL 语句。 Statement 接口不接受参数。

import java.sql.*;

public class ClickHouseClient {
  private static final String URL = "jdbc:clickhouse://:[/]";
  private static final String USER = "your username";
  private static final String PASSWORD = "your password";

  public static void main(String[] args) {
    Connection connection = null;
    Statement statement = null;

    try {
      // 注册JDBC驱动
      Class.forName("ru.yandex.clickhouse.ClickHouseDriver");

      // 打开连接
      connection = DriverManager.getConnection(URL, USER, PASSWORD);
      System.out.println("connected database successfully");

      // 执行查询
      statement = connection.createStatement();
      String sql = "select * from database.table_name limit 10";
      ResultSet rs = statement.executeQuery(sql);

      // 从结果集中提取数据
      while (rs.next()){
        String name = rs.getString("name");
        float size = rs.getFloat("size");
        System.out.println(name + " " + size);
      }

      rs.close();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (SQLException throwables) {
      throwables.printStackTrace();
    }finally {
      // 释放资源
      try {
        if(statement!=null){
          statement.close();
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }

      try {
        if(connection!=null){
          connection.close();
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }
    }
  }
}

2.2 PreparedStatement接口

PreparedStatement计划多次使用 SQL 语句, PreparedStatement 接口运行时接受输入的参数。

import java.sql.*;

public class ClickHouseClient2 {
  private static final String URL = "jdbc:clickhouse://:[/]";
  private static final String USER = "your username";
  private static final String PASSWORD = "your password";

  public static void main(String[] args) {
    Connection connection = null;
    // 注意这里使用的CK自己实现的PreparedStatement
    ClickHousePreparedStatement statement  = null;  

    try {
      // 注册JDBC驱动
      Class.forName("ru.yandex.clickhouse.ClickHouseDriver");

      // 打开连接
      connection = DriverManager.getConnection(URL, USER, PASSWORD);
      System.out.println("connected database successfully");

      // 执行查询
      String sql = "select * from database.table_name where name = ?";
      ClickHousePreparedStatement statement = (ClickHousePreparedStatement)connection.prepareStatement(sql);
      statement.setString(1, "bjehp");
      ResultSet rs = statement.executeQuery();  

      // 打印填充后的SQL语句(ck实现的PreparedStatement类包含了打印sql语句的方法)
      System.out.println("execute: " + statement.asSql());   

      // 从结果集中提取数据
      while (rs.next()){
        String name = rs.getString("name");
        float size = rs.getFloat("size");
        System.out.println(name + " " + size);
      }

      rs.close();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (SQLException throwables) {
      throwables.printStackTrace();
    }finally {
      // 释放资源
      try {
        if(statement!=null){
          statement.close();
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }

      try {
        if(connection!=null){
          connection.close();
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }
    }
  }
}

这里要注意的是,在调用executeQuery方法时,Statement需要传入sql参数,而PreparedStatement无需传入sql参数,因为在创建PrepareStatement对象时,已经传入sql参数。PrepareStatement可以使用占位符,会对传入的sql进行预编译,批处理比Statement效率高。


上一篇:反射实战 使用反射,对JDBC进行强封装


下一篇:JDBC封装使用