天天看點

使用JDBC程式設計通路ODPS

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 上。歡迎各位開源熱心人士積極回報,貢獻代碼。