添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

JDBC

更新时间:

本文将介绍如何在 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

JDBC 驱动(42.2.9.1.6)

阿里云提供了兼容 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
     * 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
      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 作为数据源,步骤如下所示:

  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