本文將介紹如何在Java應用中使用JDBC串連PolarDB PostgreSQL版(相容Oracle)資料庫。
前提條件
背景資訊
JDBC(Java Database Connectivity)為Java應用程式提供了訪問資料庫的編程介面。PolarDB PostgreSQL版(相容Oracle)資料庫的JDBC是基於開源的PostgreSQL JDBC開發而來,使用PostgreSQL本網協議進行通訊,允許Java程式使用標準的、獨立於資料庫的Java代碼串連資料庫。
JDBC驅動程式使用了PostgreSQL 3.0協議,與Java 6(JDBC 4.0)、Java 7(JDBC4.1)和Java 8(JDBC4.2)相容。
下載JDBC
阿里雲提供了相容Java 6、Java 7和Java 8三個Java版本的JDBC驅動,對應三個Jar包,包名分別為polardb-jdbc16.jar
、polardb-jdbc17.jar
和polardb-jdbc18.jar
。您可根據應用使用的JDK版本選擇合適的JDBC。
配置JDBC
在Java應用中使用JDBC前,需要將JDBC驅動包的路徑添加至CLASSPATH
中。例如您的JDBC驅動放置的路徑為/usr/local/polardb/share/java/,在CLASSPATH
中添加JDBC驅動路徑的命令如下:
export CLASSPATH=$CLASSPATH:/usr/local/polardb/share/java/<安裝的Jar包名.jar>
樣本:
export CLASSPATH=$CLASSPATH:/usr/local/polardb/share/java/polardb-jdbc18.jar
您可以通過如下命令查看當前使用的JDBC版本:
#java -jar <安裝的Jar包名.jar>
樣本:
#java -jar polardb-jdbc18.jar
POLARDB JDBC Driver 42.2.XX.XX.0
訪問PolarDB
樣本
package com.aliyun.polardb; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * POLARDB JDBC DEMO * <p> * Please make sure the host ip running this demo is in you cluster's white list. */ public class PolarDBJdbcDemo { /** * Replace the following information. */ private final String host = "***.o.polardb.rds.aliyuncs.com"; private final String user = "***"; private final String password = "***"; private final String port = "1521"; private final String database = "db_name"; public void run() throws Exception { Connection connect = null; Statement statement = null; ResultSet resultSet = null; try { Class.forName("com.aliyun.polardb.Driver"); Properties props = new Properties(); props.put("user", user); props.put("password", password); String url = "jdbc:polardb://" + host + ":" + port + "/" + database; connect = DriverManager.getConnection(url, props); /** * create table foo(id int, name varchar(20)); */ String sql = "select id, name from foo"; statement = connect.createStatement(); resultSet = statement.executeQuery(sql); while (resultSet.next()) { System.out.println("id:" + resultSet.getInt(1)); System.out.println("name:" + resultSet.getString(2)); } } catch (Exception e) { e.printStackTrace(); throw e; } finally { try { if (resultSet != null) resultSet.close(); if (statement != null) statement.close(); if (connect != null) connect.close(); } catch (SQLException e) { e.printStackTrace(); throw e; } } } public static void main(String[] args) throws Exception { PolarDBJdbcDemo demo = new PolarDBJdbcDemo(); demo.run(); } }
載入JDBC驅動
在應用中執行以下命令載入 JDBC 驅動:
Class.forName("com.aliyun.polardb.Driver");
串連資料庫
在JDBC中,一個資料庫通常用一個URL來表示,樣本如下。
jdbc:polardb://pc-***.o.polardb.rds.aliyuncs.com:1521/polardb_test?user=test&password=Pw123456
參數
樣本
說明
URL首碼
jdbc:polardb://
串連PolarDB的URL統一使用
jdbc:polardb://
作為首碼。串連地址
pc-***.o.polardb.rds.aliyuncs.com
PolarDB叢集的串連地址,如何查看串連地址請參見查看或申請串連地址。
連接埠
1521
PolarDB叢集的連接埠,預設為1521。
資料庫
polardb_test
需要串連的資料庫名。
使用者名稱
test
PolarDB叢集的使用者名稱。
密碼
Pw123456
PolarDB叢集使用者名稱對應的密碼。
查詢並處理結果
訪問資料庫執行查詢時,需要建立一個
Statement
、PreparedStatment
或者CallableStatement
對象。上述樣本中使用了
Statement
,使用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)); }
CallableStatement
用於處理預存程序,樣本如下:String sql = "{?=call getName (?, ?, ?)}"; CallableStatement stmt = conn.prepareCall(sql); stmt.registerOutParameter(1, java.sql.Types.INTEGER); //Bind IN parameter first, then bind OUT parameter int id = 100; stmt.setInt(2, id); // This would set ID as 102 stmt.registerOutParameter(3, java.sql.Types.VARCHAR); stmt.registerOutParameter(4, java.sql.Types.INTEGER); //Use execute method to run stored procedure. stmt.execute(); //Retrieve name with getXXX method String name = stmt.getString(3); Integer msgId = stmt.getInt(4); Integer result = stmt.getInt(1); System.out.println("Name with ID:" + id + " is " + name + ", and messegeID is " + msgId + ", and return is " + result);
以上代碼使用的預存程序
getName
如下:CREATE OR REPLACE FUNCTION getName( id In Integer, name Out Varchar2, result Out Integer ) Return Integer Is ret Int; Begin ret := 0; name := 'Test'; result := 1; Return(ret); End;
說明當預存程序為遊標類型時,不同的Java版本對應的遊標類型不同:
Java8及以後的版本使用
Types.REF_CURSOR
類型遊標。Java8之前的版本使用
Types.REF
類型遊標。
設定FetchSize
預設情況下,驅動會一次性從資料庫端擷取所有資料,對於資料量很大的查詢,這會佔用用戶端大量記憶體,甚至造成 OOM,為避免此類情況,JDBC提供了基於遊標的ResultSet,批量擷取資料集。使用方法如下:
設定FetchSize,FetchSize預設為0,即擷取所有資料。
設定串連的autoCommit為false。
// make sure autocommit is off conn.setAutoCommit(false); Statement st = conn.createStatement(); // Set fetchSize to use cursor st.setFetchSize(50); ResultSet rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("a row was returned."); } rs.close(); // Reset fetchSize to turn off the cursor st.setFetchSize(0); rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("many rows were returned."); } rs.close(); // Close the statement. st.close();
Maven工程
如果您的Java專案使用Maven構建,可以通過如下命令將PolarDB的JDBC驅動包安裝至您的本地倉庫:
mvn install:install-file -DgroupId=com.aliyun -DartifactId=<安裝的Jar包名> -Dversion=1.1.2 -Dpackaging=jar -Dfile=/usr/local/polardb/share/java/<安裝的Jar包名.jar>
樣本:
mvn install:install-file -DgroupId=com.aliyun -DartifactId=polardb-jdbc18 -Dversion=1.1.2 -Dpackaging=jar -Dfile=/usr/local/polardb/share/java/polardb-jdbc18.jar
在Maven工程的pom.xml
檔案中添加如下依賴。
<dependency>
<groupId>com.aliyun</groupId>
<artifactId><安裝的Jar包名></artifactId>
<version>1.1.2</version>
</dependency>
樣本:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>polardb-jdbc18</artifactId>
<version>1.1.2</version>
</dependency>
Hibernate
如果您的工程使用Hibernate串連資料庫,請在您的Hibernate設定檔hibernate.cfg.xml
中配置PolarDB資料庫的驅動類和方言。
Hibernate需要為3.6及以上版本才支援PostgresPlusDialect方言。
<property name="connection.driver_class">com.aliyun.polardb.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>
Druid串連池
Druid 1.1.24及其之後的版本預設支援PolarDB的驅動,無需設定
driver name
和dbtype
參數。Druid 1.1.24之前的版本,需要顯式設定
driver name
和dbtype
參數,如下所示:dataSource.setDriverClassName("com.aliyun.polardb.Driver"); dataSource.setDbType("postgresql");
說明Druid 1.1.24之前版本沒有適配PolarDB,因此
dbtype
需要設定為postgresql
。
如果您需要在Druid串連池中對資料庫密碼進行加密,請參見資料庫密碼加密。
適配Activiti
如果您的應用使用了商務程序管理架構Activiti,在PolarDB資料來源初始化時,可能會出現以下錯誤資訊。
couldn't deduct database type from database product name 'POLARDB Database Compatible with Oracle'
這是因為Activiti內建了一些資料庫版本資訊和資料庫類型的映射關係,導致無法正確映射PolarDB版本資訊。您可以通過設定SpringProcessEngineConfiguration
子類,在該子類中重載buildProcessEngine
的方法來解決問題。在該解決方案中,您需要顯式指定資料庫類型,配置方法請參見以下樣本。
package com.aliyun.polardb;
import org.activiti.engine.ProcessEngine;
import org.activiti.spring.SpringProcessEngineConfiguration;
public class PolarDBSpringProcessEngineConfiguration extends SpringProcessEngineConfiguration {
public PolarDBSpringProcessEngineConfiguration() {
super();
}
@Override
public ProcessEngine buildProcessEngine() {
setDatabaseType(DATABASE_TYPE_POSTGRES);
return super.buildProcessEngine();
}
}
將SpringProcessEngineConfiguration
子類放在您的工程中,在設定檔中設定使用該類載入配置,並初始化引擎,具體資訊請參見以下樣本。
<bean id="processEngineConfiguration" class="com.aliyun.polardb.PolarDBSpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="databaseSchemaUpdate" value="true"/>
<!-- 其他配置在此省略 -->
</bean>
適配Quartz
Quartz是一款開源的作業調度庫,使用Quartz串連PolarDB時,需要將org.quartz.jobStore.driverDelegateClass
配置為 org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
,如下所示:
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
適配WebSphere
使用 WebSphere時,配置PolarDB的JDBC作為資料來源,步驟如下所示:
資料庫類型選擇使用者自訂的。
實作類別名為:
com.aliyun.polardb.ds.PGConnectionPoolDataSource
。類直接選取JDBC jar包所在路徑。
適配MyBatis
使用MyBatis時,可能需要配置databaseIdProvider,預設配置如下所示:
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
databaseIdProvider的目的是提供一個資料庫產品名到特定名稱(即databaseId)的映射關係,即便資料庫的產品名因資料庫版本變化而發生改變,也可以映射到相同的名稱。
在MyBatis的XML對應檔中,可以為SQL語句指定databaseId屬性,說明該SQL僅能夠在該databaseId對應的資料庫上執行。因此,在載入XML對應檔時,MyBatis僅載入databaseId與當前資料庫匹配的SQL語句,如果SQL語句沒有設定databaseId屬性則總是會被載入。
因此,如果XML對應檔中的SQL均沒有指定databaseId,預設配置資訊可以不做任何修改。如果需要通過databaseId識別特定於PolarDB執行的SQL,則可以添加如下配置資訊,並在XML對應檔中使用polardb作為SQL的databaseId。
<property name="POLARDB" value="polardb" />
常見問題
Q:如何選擇JDBC驅動,是否可以使用開源社區驅動?
A:PolarDB PostgreSQL版(相容Oracle)相容版在開源PostgreSQL的基礎上實現了眾多相容性相關的特性,有些特性需要驅動層配合實現,因此,推薦使用PolarDB的JDBC驅動。相關驅動可以在官網驅動下載頁面下載。
Q:公用Maven倉庫是否有PolarDB JDBC驅動?
A:按照官網描述,JDBC驅動需要在官網下載jar包,對於Maven工程需要手動安裝該jar包至本地倉庫使用,目前僅支援官網下載JDBC驅動包一種方式。
Q:如何查看版本號碼?
A:通過運行
java -jar 驅動名
來查看版本號碼。Q:是否支援在URL中配置多個IP和連接埠?
A:PolarDB PostgreSQL版(相容Oracle)的JDBC驅動支援在URL中配置多個IP和連接埠,樣本如下:
jdbc:poalardb://1.2.XX.XX:5432,2.3.XX.XX:5432/postgres
說明配置多個IP後,建立串連時會依次嘗試通過這些IP建立串連,若都不能建立串連,則串連建立失敗。每個IP嘗試建立串連的逾時時間預設為10s,即connectTimeout,若要修改逾時時間,可在串連串中添加該參數進行設定。
Q:遊標類型如何選擇?
A:如果是java 1.8之前的JDK,使用Types.REF;如果是java 1.8及其之後的版本,可以使用Types.REF_CURSOR。
Q:是否支援預設返回大寫的列名?
A:可以在JDBC串連串中添加參數
oracleCase=true
,該參數會將返回的列名預設轉換為大寫,樣本如下:jdbc:poalardb://1.2.XX.XX:5432,2.3.XX.XX:5432/postgres?oracleCase=true