JDBC
本文將介紹如何在Java應(yīng)用中使用JDBC連接PolarDB PostgreSQL版(兼容Oracle)數(shù)據(jù)庫。
前提條件
支持PolarDB PostgreSQL版(兼容Oracle) 2.0版本。
已經(jīng)在PolarDB集群創(chuàng)建用戶,如何創(chuàng)建用戶請參見創(chuàng)建數(shù)據(jù)庫賬號。
已經(jīng)將需要訪問PolarDB集群的主機(jī)IP地址添加到白名單,如何添加白名單請參見設(shè)置集群白名單。
背景信息
JDBC(Java Database Connectivity)為Java應(yīng)用程序提供了訪問數(shù)據(jù)庫的編程接口。PolarDB PostgreSQL版(兼容Oracle)數(shù)據(jù)庫的JDBC是基于開源的PostgreSQL JDBC開發(fā)而來,使用PostgreSQL本地網(wǎng)絡(luò)協(xié)議進(jìn)行通信,允許Java程序使用標(biāo)準(zhǔn)的、獨(dú)立于數(shù)據(jù)庫的Java代碼連接數(shù)據(jù)庫。
下載驅(qū)動
JDK版本 | 軟件包 |
1.6 | |
1.7 | |
1.8 |
由于安全原因,兼容Oracle語法兼容1.0版本的驅(qū)動已經(jīng)下線。如需幫助,請加入相關(guān)群組進(jìn)行處理。
Maven配置
目前PolarDB的JDBC驅(qū)動尚未在公開的Maven倉庫中提供,當(dāng)前僅支持通過上傳JAR包的方式進(jìn)行配置。
功能介紹
連接級參數(shù)功能
以下功能都通過一個連接參數(shù)配置,支持的參數(shù)如下表所示。所有的新增參數(shù)的生效范圍都控制為連接級別,隨Connection的生命周期生效。
參數(shù)名 | 說明 |
autoCommit | 開啟或關(guān)閉參數(shù)形式的自動提交。取值如下:
|
autoCommitSpecCompliant | 是否允許自動提交下繼續(xù)調(diào)用commit/rollback方法。取值如下:
|
blobAsBytea | 是否支持Oracle兼容的BLOB。取值如下:
|
clobAsText | 是否支持Oracle兼容的CLOB。取值如下:
|
collectWarning | 是否收集告警(防止內(nèi)存溢出)。取值如下:
|
defaultPolarMaxFetchSize | 配合MaxFetchSize實現(xiàn)結(jié)果集條數(shù)控制,默認(rèn)值為0。 |
extraFloatDigits | 小數(shù)長度。 |
forceDriverType | 強(qiáng)制驅(qū)動按照某一種方案去解析。取值為pg、ora、ora11和ora14。 |
mapDateToTimestamp | 是否支持將Date類型轉(zhuǎn)為Timestamp。取值如下:
|
namedParam | 是否支持通過
|
oracleCase | 是否返回列名、表名的大寫。取值如下:
|
resetNlsFormat | 是否支持將
|
unnamedProc | 是否支持匿名塊綁定參數(shù)功能。取值如下:
|
boolAsInt | 支持Oracle語義的布爾值表示方式。取值如下:
|
escapeSyntaxCallMode | 選擇存儲過程的調(diào)用方式,取值如下:
|
數(shù)據(jù)類型解析
Date類型:64位Date類型的支持。
內(nèi)核支持了64位的Date,數(shù)據(jù)表示格式與Oracle相同,帶有時分秒信息,對應(yīng)驅(qū)動可以以Timestamp的方式去處理該Date。將所有的Date類型(Types.DATE或者DATEOID)映射成Timestamp類型,驅(qū)動將Date視為Timestamp進(jìn)行處理。
Interval類型:支持Oracle模式的Interval輸入。
PG社區(qū)的驅(qū)動不支持例如
+12 12:03:12.111
形式的Interval輸入,由于目前Oracle模式下該形式是標(biāo)準(zhǔn)輸出,所以PolarDB PostgreSQL版(兼容Oracle)支持這種形式的輸出。Number類型:支持Number的GET行為。
Java.sql的標(biāo)準(zhǔn)實現(xiàn)中沒有g(shù)etNumber相關(guān)的函數(shù),只有g(shù)etInt等函數(shù)。如果一個函數(shù)的參數(shù)類型是Number,允許使用getInt、setInt、RegisterParam等接口將參數(shù)以Int形式傳遞。
Blob類型:Blob處理為Bytea,Clob處理為Text。
針對Java.sql.Blob和Java.sql.Clob接口的實現(xiàn)。內(nèi)核已經(jīng)為Blob、Clob添加了映射,在Java層面也可以按照Bytea、Text的方式去處理。主類實現(xiàn)了getBytes、setBytes、position、getBinaryStream等方法。
Boolean類型:支持布爾類型轉(zhuǎn)義為1/0。
為了保證老版本的兼容性,
setBoolean
接口方法在設(shè)置時默認(rèn)采用true/false
。然而,用戶可以通過激活boolAsInt
參數(shù)來切換至與Oracle兼容的1/0
語義,以此適應(yīng)Oracle兼容的數(shù)據(jù)庫交互需求。
PL/SQL適配
支持不帶$$符號的存儲過程。
支持在創(chuàng)建
FUNCTION
/PROCEDURE
等過程時省略$$
符號,并支持在語法解析時截斷/
字符。支持冒號變量名作為參數(shù)。
支持使用
:xxx
這種方式傳遞參數(shù),其中xxx
為冒號開頭的變量名。支持匿名塊綁定參數(shù)。
支持屏蔽PLSQL的警告信息。
防止循環(huán)中存儲過多的警告信息導(dǎo)致內(nèi)存超限。
示例
加載JDBC驅(qū)動
在應(yīng)用中執(zhí)行以下命令加載JDBC驅(qū)動:
Class.forName("com.aliyun.polardb2.Driver");
如果是通過項目導(dǎo)入的方式導(dǎo)入JDBC,以上驅(qū)動都會自動注冊完成,不需要額外注冊。
連接數(shù)據(jù)庫
在JDBC中,一個數(shù)據(jù)庫通常用一個URL來表示,示例如下:
jdbc:polardb://pc-***.o.polardb.rds.aliyuncs.com:1521/polardb_test?user=test&password=Pw123456
參數(shù) | 示例 | 說明 |
URL前綴 | jdbc:polardb:// | 連接PolarDB的URL統(tǒng)一使用 |
連接地址 | pc-***.o.polardb.rds.aliyuncs.com | PolarDB集群的連接地址,如何查看連接地址請參見查看或申請連接地址。 |
端口 | 1521 | PolarDB集群的端口,默認(rèn)為1521。 |
數(shù)據(jù)庫 | polardb_test | 需要連接的數(shù)據(jù)庫名。 |
用戶名 | test | PolarDB集群的用戶名。 |
密碼 | Pw123456 | PolarDB集群用戶名對應(yīng)的密碼。 |
查詢并處理結(jié)果
訪問數(shù)據(jù)庫執(zhí)行查詢時,需要創(chuàng)建一個Statement、PreparedStatment或者CallableStatement對象。
使用PreparedStatment示例如下:
PreparedStatement st = conn.prepareStatement("select id, name from foo where id > ?");
st.setInt(1, 10);
resultSet = st.executeQuery();
while (resultSet.next()) {
System.out.println("id:" + resultSet.getInt(1));
System.out.println("name:" + resultSet.getString(2));
}
使用OUT參數(shù)
訪問數(shù)據(jù)庫存儲過程時,如果要使用帶有OUT參數(shù)的存儲過程,需要創(chuàng)建CallableStatement對象。并使用
registerOutParameter,使用示例如下:
String sql = "CREATE or replace PROCEDURE test_in_out_procedure(a IN integer, b INOUT integer, c OUT integer)\n" +
"AS $$\n" +
"BEGIN\n" +
" c = a + b;\n" +
" b = a;\n" +
"return;\n" +
"END;\n" +
"$$;";
conn.createStatement().execute(sql);
CallableStatement stmt = conn.prepareCall("{call test_in_out_procedure(?,?,?)}");
stmt.setInt(1, 1);
stmt.setInt(2, 2);
stmt.registerOutParameter(2, Types.INTEGER);
stmt.registerOutParameter(3, Types.INTEGER);
stmt.execute();
System.out.println("get $2 = " + stmt.getInt(2));
System.out.println("get $3 = " + stmt.getInt(3));
// OUTPUT:
// get $2 = 1
// get $3 = 3
相關(guān)工具適配
適配Hibernate
如果您的工程使用Hibernate連接數(shù)據(jù)庫,請在您的Hibernate配置文件hibernate.cfg.xml
中配置PolarDB數(shù)據(jù)庫的驅(qū)動類和方言。
Hibernate需要為3.6及以上版本才支持PostgresPlusDialect方言。
<property name="connection.driver_class">com.aliyun.polardb2.Driver</property>
<property name="connection.url">jdbc:polardb://pc-***.o.polardb.rds.aliyuncs.com:1521/polardb_test</property>
<property name="dialect">org.hibernate.dialect.PostgresPlusDialect</property>
對于表中date
類型的列,需要在Hibernate的.hbm.xml
文件中調(diào)整配置type="java.util.Date"
以確保Hibernate讀寫PolarDB的date
類型數(shù)據(jù)時保留時分秒精度。如果直接使用type="date"
,則可能造成date
精度丟失。示例配置如下:
<!-- 其他配置信息 -->
<hibernate-mapping package="com.aliyun.polardb2.demo">
<class name="TestTableEntity" table="test_table_name">
<!-- 其他列信息 -->
<property name="currentDate" column="curr_date" type="java.util.Date"/> <!-- 指定java.util.Date類型以保留date精度 -->
<!-- 其他列信息 -->
</class>
</hibernate-mapping>
Druid連接池
Druid 1.1.24之前的版本,需要顯式設(shè)置driver name
和dbtype
參數(shù),如下所示:
dataSource.setDriverClassName("com.aliyun.polardb2.Driver");
dataSource.setDbType("postgresql");
Druid 1.1.24之前版本沒有適配PolarDB,因此dbtype
需要設(shè)置為postgresql
。
如果您需要在Druid連接池中對數(shù)據(jù)庫密碼進(jìn)行加密,請參見數(shù)據(jù)庫密碼加密。
適配WebSphere
使用WebSphere時,配置PolarDB的JDBC作為數(shù)據(jù)源,步驟如下所示:
數(shù)據(jù)庫類型選擇用戶自定義的。
實現(xiàn)類名為:
com.aliyun.polardb2.ds.PGConnectionPoolDataSource
。類路徑選擇JDBC jar包所在路徑。
常見問題
如何選擇JDBC驅(qū)動,是否可以使用開源社區(qū)驅(qū)動?
PolarDB PostgreSQL版(兼容Oracle)兼容版在開源PostgreSQL的基礎(chǔ)上實現(xiàn)了眾多兼容性相關(guān)的特性,有些特性需要驅(qū)動層配合實現(xiàn),因此,推薦使用PolarDB的JDBC驅(qū)動。相關(guān)驅(qū)動可以在官網(wǎng)驅(qū)動下載頁面下載。
公共Maven倉庫是否有PolarDB JDBC驅(qū)動?
按照官網(wǎng)描述,JDBC驅(qū)動需要在官網(wǎng)下載jar包,對于Maven工程需要手動安裝該jar包至本地倉庫使用,目前僅支持官網(wǎng)下載JDBC驅(qū)動包一種方式。
如何查看版本號?
通過運(yùn)行java -jar 驅(qū)動名
來查看版本號。
是否支持在URL中配置多個IP和端口?
PolarDB PostgreSQL版(兼容Oracle)的JDBC驅(qū)動支持在URL中配置多個IP和端口,示例如下:
jdbc:polardb://1.2.XX.XX:5432,2.3.XX.XX:5432/postgres
配置多個IP后,創(chuàng)建連接時會依次嘗試通過這些IP創(chuàng)建連接,若都不能創(chuàng)建連接,則連接創(chuàng)建失敗。每個IP嘗試創(chuàng)建連接的超時時間默認(rèn)為10s,即connectTimeout,若要修改超時時間,可在連接串中添加該參數(shù)進(jìn)行設(shè)置。
游標(biāo)類型如何選擇?
如果是java 1.8之前的JDK,使用Types.REF;如果是java 1.8及其之后的版本,可以使用Types.REF_CURSOR。
是否支持默認(rèn)返回大寫的列名?
可以在JDBC連接串中添加參數(shù)oracleCase=true
,該參數(shù)會將返回的列名默認(rèn)轉(zhuǎn)換為大寫,示例如下:
jdbc:polardb://1.2.XX.XX:5432,2.3.XX.XX:5432/postgres?oracleCase=true
版本更新日志
版本45.4.0.10.6(2024-12-04)
支持高版本JDBC的
Channel Binding
功能。升級
escapeSyntaxCallMode
參數(shù)默認(rèn)值為callIfNoReturn
,適配Oracle的參數(shù)綁定行為。修復(fù)
attidentity
識別錯誤可能導(dǎo)致的列類型獲取不正確缺陷。
版本45.4.0.10.5(2024-10-24)
優(yōu)化
resetNlsFormat
參數(shù)的設(shè)置,確保連接時的正確配置。同時,避免在審計日志中留下非預(yù)期的執(zhí)行記錄。修復(fù)邏輯復(fù)制測試中因無法識別
java.nio.Buffer
類型接口而導(dǎo)致的錯誤。修復(fù)存儲過程中
CASE WHEN...END
識別結(jié)束解析不正確的問題。
版本45.4.0.10.4(2024-09-02)
修復(fù)了PL塊中綁定不正確的問題。針對此問題對性能的影響,默認(rèn)已關(guān)閉該功能。
支持在同一類型內(nèi)部進(jìn)行隱式轉(zhuǎn)換,允許字符類型(如
VARCHAR
、CHAR
)和數(shù)字類型(如NUMERIC
、INTEGER
、DOUBLE
)作為INOUT
參數(shù)相互轉(zhuǎn)換。驅(qū)動中元信息的
getDatabaseProductName()
函數(shù)返回值現(xiàn)為:“POLARDB2 Database Compatible with Oracle
”。
版本45.4.0.10.2(2024-07-19)
修復(fù)了在
Mybatis
中,當(dāng)對象實體注冊類型為Timestamp
時,數(shù)據(jù)庫無法正確推斷參數(shù)類型的問題。
專家面對面
關(guān)于JDBC,如果您在使用過程中有任何問題,請進(jìn)釘釘群咨詢。釘釘群號:71365019522。