MaxCompute JDBC
MaxCompute JDBC驱动是MaxCompute提供的Java数据库连接(Java Database Connectivity)接口,可以通过标准的JDBC编程基于MaxCompute执行海量数据的分布式计算查询。MaxCompute JDBC驱动还可以用于连接MaxCompute和支持JDBC的工具。使用说明文档见:MaxCompute JDBC概述。
通过MaxCompute JDBC驱动执行SQL并获取结果,需要执行账号满足以下要求:
- 是项目空间的成员。
- 有项目空间中CreateInstance权限。
- 有目标表的Select与Download权限。
第三方工具的使用具体见MaxCompute文档:
- 使用JDBC连接Tableau,对MaxCompute中的数据进行可视化分析。详情请参见配置JDBC使用Tableau。
- 使用JDBC连接SQL Workbench/J,对MaxCompute中的数据执行SQL语句。详情请参见配置JDBC使用SQL Workbench/J。
一些常见问题
是否支持连接池与Auto-Commit?
MaxCompute本身提供Rest服务,和传统数据库维持长连接的方式十分不同。MaxCompute JDBC驱动创建Connection是十分轻量的操作,因此并无必要针对MaxCompute JDBC刻意使用连接池。当然,MaxCompute JDBC也支持使用连接池的场景。
由于MaxCompute不支持Transaction,每个查询动作都会即时体现到服务端,即默认为Auto-Commit的行为。因此MaxCompute JDBC驱动不支持关闭Auto-Commit模式。
如何获取MaxCompute Logview URL?
MaxCompute JDBC驱动是基于MaxCompute Java SDK的封装。因此,与MaxCompute客户端、MaxCompute Studio以及Dataworks一样,通过MaxCompute JDBC驱动执行SQL时,会生成Logview URL。您可以通过Logview查看任务执行状态,追踪任务进度,获取任务执行结果。Logview URL可以通过properties.log4j进行配置,默认打印到STDERR。
MaxCompute JDBC使用说明
JDBC Maven依赖
通过Maven方式使用MaxCompute JDBC的项目对象模型POM(Project Object Model)示例片段如下。
<dependency>
<groupId>com.aliyun.odps</groupId>
<artifactId>odps-jdbc</artifactId>
<version>3.0.1</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
连接MaxCompute
1. 加载MaxCompute JDBC驱动:
Class.forName("com.aliyun.odps.jdbc.OdpsDriver");
2. 通过DriverManager创建Connection:
Connection cnct = DriverManager.getConnection(url, accessId, accessKey);
参数说明如下:
- url:格式为
jdbc:odps:<MaxCompute endpoint>?project=<MaxCompute project name>
。 其中:举例如下。jdbc:odps:http://service.cn-hangzhou.maxcompute.aliyun.com/api?project=test_project
- <maxcompute_endpoint>为自己MaxCompute服务所在区域的Endpoint。例如,华东1(杭州)区域的外网Endpoint为
http://service.cn-hangzhou.maxcompute.aliyun.com/api
。更多关于Endpoint的配置信息,请参见配置Endpoint。 - <maxcompute_project_name> 为自己的MaxCompute项目空间名称。
- <maxcompute_endpoint>为自己MaxCompute服务所在区域的Endpoint。例如,华东1(杭州)区域的外网Endpoint为
- accessId:创建项目空间的AccessKey ID。
- accessKey:创建项目空间的AccessKey ID对应的AccessKey Secret。
3. 执行查SQL语句:
Statement stmt = cnct.createStatement();
ResultSet rset = stmt.executeQuery("SELECT foo FROM bar");
while (rset.next()) {
// process the results
}
rset.close();
stmt.close();
conn.close();
示例代码
1. 删除表,创建表,获取Metadata:
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(DRIVER_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection conn = DriverManager.getConnection(
"jdbc:odps:<maxcompute endpoint>?project=<maxcompute project>",
"aliyun accessId", "aliyun accessKey");
// create a table
Statement stmt = conn.createStatement();
final String tableName = "jdbc_test";
stmt.execute("DROP TABLE IF EXISTS " + tableName);
stmt.execute("CREATE TABLE " + tableName + " (key BIGINT, value STRING)");
// get meta data
DatabaseMetaData metaData = conn.getMetaData();
System.out.println("product = " + metaData.getDatabaseProductName());
System.out.println("jdbc version = "
+ metaData.getDriverMajorVersion() + ", "
+ metaData.getDriverMinorVersion());
ResultSet tables = metaData.getTables(null, null, tableName, null);
while (tables.next()) {
String name = tables.getString("TABLE_NAME");
System.out.println("inspecting table: " + name);
ResultSet columns = metaData.getColumns(null, null, name, null);
while (columns.next()) {
System.out.println(
columns.getString("COLUMN_NAME") + "\t" +
columns.getString("TYPE_NAME") + "(" +
columns.getInt("DATA_TYPE") + ")");
}
columns.close();
}
tables.close();
stmt.close();
conn.close();
}
}
预期输出:
product = MaxCompute/ODPS
jdbc version = 3, 0
inspecting table: jdbc_test
key BIGINT(-5)
value STRING(12)
2. 执行INSERT:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(DRIVER_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection conn = DriverManager.getConnection(
"jdbc:odps:http://10.101.222.162:8002/odps_dailyrunnew?project=odps_mingyou_test",
"63wd3dpztlmb5ocdkj94pxmm", "oRd30z7sV4hBX9aYtJgii5qnyhg=");
Statement stmt = conn.createStatement();
// The following DML also works
//String dml = "INSERT INTO jdbc_test SELECT 1, \"foo\"";
String dml = "INSERT INTO jdbc_test VALUES(1, \"foo\")";
int ret = stmt.executeUpdate(dml);
assert ret == 1;
stmt.close();
conn.close();
}
}
3. 执行批量INSERT:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(DRIVER_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection conn = DriverManager.getConnection(
"jdbc:odps:<maxcompute endpoint>?project=<maxcompute project>",
"aliyun accessId", "aliyun accessKey");
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO jdbc_test VALUES(?, ?)");
pstmt.setLong(1, 1L);
pstmt.setString(2, "foo");
pstmt.addBatch();
pstmt.setLong(1, 2L);
pstmt.setString(2, "bar");
pstmt.addBatch();
int[] ret = pstmt.executeBatch();
assert ret[0] == 1;
assert ret[1] == 1;
pstmt.close();
conn.close();
}
}
4. 执行SELECT:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(DRIVER_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection conn = DriverManager.getConnection(
"jdbc:odps:<maxcompute endpoint>?project=<maxcompute project>",
"aliyun accessId", "aliyun accessKey");
ResultSet rs;
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM JDBC_TEST";
stmt.executeQuery(sql);
ResultSet rset = stmt.getResultSet();
while (rset.next()) {
System.out.println(String.valueOf(rset.getInt(1)) + "\t" + rset.getString(2));
}
}
}