odps 提供了自己的 java sdk 作為程式設計接口。但是對于大多數來自傳統關系資料庫的使用者來說,為了完成一些簡單任務再學習一套 sdk,成本效益頗低。odps-jdbc 可以較好的解決這個問題。通過 odps-jdbc 可以輕松完成類似執行 select 語句,并獲得結果集這樣的任務。
建立任意 java 項目,從 maven 添加 odps-jdbc 作為依賴(位于 maven 主倉-http://search.maven.org/#artifactdetails%7ccom.aliyun.odps%7codps-jdbc%7c1.0-public%7cjar):
<dependency>
<groupid>com.aliyun.odps</groupid>
<artifactid>odps-jdbc</artifactid>
<version>1.0-public</version>
</dependency>
參考如下示例代碼,包含了删表、建表、擷取表 meta、執行 insert、執行 select 以及周遊結果集等常見操作:
import java.sql.connection;
import java.sql.databasemetadata;
import java.sql.drivermanager;
import java.sql.resultset;
import java.sql.sqlexception;
import java.sql.statement;
import java.util.properties;
public class main {
private static string drivername = “com.aliyun.odps.jdbc.odpsdriver”;
public static void main(string[] args) throws sqlexception {
try {
class.forname(drivername);
} catch (classnotfoundexception e) {
e.printstacktrace();
system.exit(1);
}
properties config = new properties();
config.put(“access_id”, “your_access_id”);
config.put(“access_key”, “your_access_key”);
config.put(“project_name”, “your_project”);
config.put(“charset”, “utf-8″);
connection
conn = drivermanager.getconnection(“jdbc:odps:https://service.odps.aliyun.com/api”, config);
resultset rs;
// create a table
statement stmt = conn.createstatement();
string tablename = “jdbc_test”;
stmt.execute(“drop table if exists ” + tablename);
stmt.execute(“create table ” + tablename + ” (key int, value string)”);
// get meta data
databasemetadata metadata = conn.getmetadata();
system.out.println(“product = ” + metadata.getdatabaseproductname());
system.out.println(“jdbc version = ” + metadata.getdrivermajorversion() + “, ”
+ metadata.getdriverminorversion());
rs = metadata.gettables(null, null, tablename, null);
while (rs.next()) {
string name = rs.getstring(3);
system.out.println(“inspecting table: ” + name);
resultset rs2 = metadata.getcolumns(null, null, name, null);
while (rs2.next()) {
system.out.println(rs2.getstring(“column_name”) + “\t”
+ rs2.getstring(“type_name”) + “(” + rs2.getint(“data_type”) + “)”);
// run sql
string sql;
// insert a record
sql = string.format(“insert into table %s select 24 key, ‘hours’ value from (select count(1) from %s) a”, tablename, tablename);
system.out.println(“running: ” + sql);
int count = stmt.executeupdate(sql);
system.out.println(“updated records: ” + count);
// select * query
sql = “select * from ” + tablename;
rs = stmt.executequery(sql);
system.out.println(string.valueof(rs.getint(1)) + “\t” + rs.getstring(2));
運作可以獲得類似如下結果:
product = odps jdbc
jdbc version = 1, 0
inspecting table: jdbc_test
key bigint(-5)
value string(12)
running: insert into table jdbc_test select 24 key, ‘hours’ value from (select count(1) from jdbc_test) a
updated records: 1
running: select * from jdbc_test
24 hours
這裡列一下使用 odps-jdbc 可能要注意的事項:
目前 odps-jdbc 的實作,類似 select 這樣的查詢會在 odps 中生成臨時表,表名為 jdbc_temp_tbl_$uuid。這些臨時表會在 statement.close 和 connection.close 的時候被删除。如果忘記了調用 close,這些表會遺留在 odps 中,預設生命周期是 3 天。
odps-jdbc 雖然可以完成 insert into 動作,但并不适合如傳統關系資料庫那樣密集執行每次 insert 一條記錄的場景。每次 insert into 會啟動一個 instance,執行時間可能需要數秒。
并不是所有 odpscmd 指令都被 statement 支援。statement 隻接受 sql 語句,例如 set、grant 等都不是 sql。
不支援 select null。目前 odps 無法支援 create table … as select …, null, …,是以在 statement 中寫帶有 null 的 select 會出錯。
我們的目的是使 odps 更加開放、靈活和易用。目前 odps-jdbc 已經完成集團的開源流程,托管在 github-https://github.com/aliyun/aliyun-odps-jdbc 上。歡迎各位開源熱心人士積極回報,貢獻代碼。