Java Database Connectivity(JDBC),是Java语言中用来规范客户端程序访问数据库的API,提供了查询、插入、更新数据库中数据的方法。下面将简单探讨JDBC的基础知识,以及关于JDBC driver的开源实现。
基本概念
JDBC是一种规范,提供完整的接口供应用程序访问底层数据库。简单的说JDBC是Java应用程序与不同数据库的连接桥梁,使用Java就能对数据库进行CURD操作。由于在现实中数据库是由不同的生产厂商决定的,例如MySQL、OceanBase、ODPS等等,数据库厂商根据JDBC规范实现了各自的应用驱动程序,用户可以根据实际情况调用对应的驱动来访问数据库。
在使用JDBC的过程中主要使用到4个接口
-
Driver接口: Driver接口一般是由数据库厂家提供,应用程序只需要调用相应的接口就可以了。例如下面分别连接MySQL与Oracle时装载的驱动程序:
Class.forName("com.mysql.jdbc.Driver"); Class.forName("oracle.jdbc.driver.OracleDriver");
-
Connection接口: 该接口主要负责与特定数据库创建链接,提交SQL语句并接收返回结果。例如创建MySQL数据库的链接过程:
Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
下面是一些常用的方法。
// 创建Statement对象,该对象封装String类型的SQL语句。 conn.createStatement(); // 创建PrepareStatement对象,该对象封装了预编译的SQL语句。 conn.prepareStatement(); // 提交事务 conn.commit(); // 回滚事务 conn.rollback();
-
Statement接口: 用于执行静态SQL语句并返回它所生成结果的对象。Statement接口有三类,分别是:
-
Statement: 提供执行语句和获取结果的基本方法,对数据库进行通用访问,支持批量更新、批量删除。一般用于执行静态SQL语句,不接受参数。
-
PreparedStatement: 继承自Statement,支持可变参数的SQL语句,添加了处理IN参数的方法,安全性比较好。
-
CallableStatement: 继承自PreparedStatement,支持调用存储过程。
常见的Statement方法有:
// 运行语句 statement.execute(String SQL); // 运行Select语句,返回结果集 statement.executeQuery(String SQL); // 运行Insert、Update、Delete语句,返回更新的行数 statement.executeUpdate(String SQL); // 向数据库发送一批SQL语句 statement.executeBatch();
-
-
ResultSet接口: 该接口提供对不同类型字段检索的方法。常用的有:
resultSet.getString() resultSet.getFloat() resultSet.getDate() resultSet.getBoolean() resultSet.getObject()
JDBC的运行过程
应用JDBC的过程中一般经历这么几个阶段。
注册驱动程序
例如要对MySQL数据库进行访问,调用MySQL的JDBC驱动。
Class.forName("com.mysql.jdbc.Driver");
建立数据库连接Connection
String url = "jdbc:mysql://host:port/database";
Connection conn = DriverManager.getConnection(url, user, password);
创建执行SQL语句的Statement
String id = "1";
String sql = "DELETE FROM table WHERE id =" + id;
Statement st = conn.createStatement();
st.executeQuery(sql);
上述的方法中存在SQL注入的危险,因为sql语句是简单的拼接,如果传入的id变量的值为”1 or 1=1”,那么将会删除表中的所有记录。
String sql = "INSERT INTO user (name, pwd) VALUES (?,?)";
PreparedStatement ps = conn.preparedStatement(sql);
ps.setString(1, "col_value");
ps.setString(2, "123456");
ps.executeQuery();
上述的方法中能够防止SQL注入,因为sql语句在程序运行前已经完成了编译,在运行时动态把参数传入到PreparedStatement时,传入的内容被转义为字段的属性值而不是SQL语句。
获得执行结果ResultSet
ResultSet rs = ps.executeQuery();
while(rs.next()){
rs.getString("col_name");
rs.getInt(1);
}
释放资源
resultSet.close();
statement.close();
connection.close();
Apache Calcite进行JDBC多数据源关联
Apache Calcite是一个动态数据管理系统,提供标准的SQL语言、多种查询优化和连接各种数据源的能力,是在大数据领域中常见的查询引擎。Calcite的目标是“one size fits all”(一种方案适应所有需求场景),希望为不同计算平台和数据源提供统一的查询引擎。由于Calcite本身与数据存储和处理的逻辑无关,因此它成为了与多个数据存储位置(数据源)和多种数据处理引擎之间进行联调的解决方案。
假设有一个场景,我们需要从两个不同的数据库中读取数据并进行关联,这个过程可以使用Calcite的JDBC Adapter来实现。下面是一个简单的例子:
public void multiSourceTest() throws SQLException {
Properties config = new Properties();
config.put("model", TestUtil.resourcePath("multiSource.json"));
config.put("lex", "MYSQL");
String sql ="/*SQL*/";
try (Connection con = DriverManager.getConnection("jdbc:calcite:", config)) {
try (Statement stmt = con.createStatement()) {
try (ResultSet rs = stmt.executeQuery(sql)) {
printRs(rs);
}
}
}
}
上述代码跟JDBC的调用过程类似,先建立Connection,然后创建Statement并执行SQL语句,然后获得返回结果ResultSet。Calcite架构中定义了Adapter概念,每个数据源的Adapter定义了model、schema、schema Factory。model定义了数据源的物理属性,也即是后端数据库的基本属性。上述代码中首先定义了model,获取不同数据源的属性。将lex设定为MYSQL可以在内部解析验证SQL过程中忽略大小写敏感。我的个人理解是Calcite的JDBC相比于其他JDBC驱动能够支持对不同数据源的操作。
Apache Calcite Avatica
Avatica是Calcite项目的一个子项目,这是一个构建数据库驱动程序的框架。上面看到的很多代码实例都是讲述客户端如何使用JDBC驱动来连接数据库进行操作,那么如何实现自己的JDBC驱动呢?这是我目前正在学习摸索中的问题,后面会再补充新的文章。
在Avatica中有三个核心的概念,通过AvaticaFactory来实现JDBC的4个重要接口(Driver,Connection,Statement,ResultSet),下面是官网的描述:
- Meta: Meta is a local API sufficient to implement any Avatica provider.
- AvaticaFactory: AvaticaFactory creates implementations of the JDBC classes on top of a Meta.
- Service: Service is an interface that implements the functions of Meta in terms of request and response command objects.
参考资料
- 使用Apache Calcite进行JDBC多数据源关联,https://zhuanlan.zhihu.com/p/143935885
- Apache顶级项目Calcite使用介绍,https://www.sohu.com/a/296117762_100123073
- 基于Calcite自定义JDBC Driver,https://blog.csdn.net/dafei1288/article/details/103485689
- Calcite Avatica,https://calcite.apache.org/avatica/docs/index.html