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));
}
}
}