全部產品
Search
文件中心

PolarDB:JDBC

更新時間:Sep 03, 2024

本文將介紹如何在Java應用中使用JDBC串連PolarDB PostgreSQL版(相容Oracle)資料庫。

前提條件

  • 已經在PolarDB叢集建立使用者,如何建立使用者請參見建立資料庫帳號

  • 已經將需要訪問PolarDB叢集的主機IP地址添加到白名單,如何添加白名單請參見設定叢集白名單

背景資訊

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

JDBC驅動(42.2.9.1.6)

阿里雲提供了相容Java 6、Java 7和Java 8三個Java版本的JDBC驅動,對應三個Jar包,包名分別為polardb-jdbc16.jarpolardb-jdbc17.jarpolardb-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叢集使用者名稱對應的密碼。

  • 查詢並處理結果

    訪問資料庫執行查詢時,需要建立一個StatementPreparedStatment或者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,批量擷取資料集。使用方法如下:

    • 設定FetchSizeFetchSize預設為0,即擷取所有資料。

    • 設定串連的autoCommitfalse

    // 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 namedbtype參數。

  • Druid 1.1.24之前的版本,需要顯式設定driver namedbtype參數,如下所示:

    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作為資料來源,步驟如下所示:

  1. 資料庫類型選擇使用者自訂的

  2. 實作類別名為:com.aliyun.polardb.ds.PGConnectionPoolDataSource

  3. 類直接選取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