日本語PDF

2 JDBC、UCPおよびデータベースにおけるJavaの簡単な紹介

Oracle Databaseは、データの格納、変更および使用に使用できるリレーショナル・データベースです。

Javaアプリケーションでは、リレーショナル・データベースのデータのアクセスおよび操作に、Java Database Connectivity(JDBC)標準が使用されます。

業界標準のアプリケーション・プログラミング・インタフェース(API)であるJDBCを使用すると、JavaからSQLを使用してRDBMSにアクセスできます。JDBCは、JDBCエスケープ標準のエントリ・レベルに準拠しています。ベンダー各社はそれぞれ独自の拡張を含めたJDBC仕様を実装しています。

ユニバーサル接続プール(UCP)は、接続を再利用するためにデータベース接続オブジェクトをキャッシュするために使用する接続プールです。これにより、パフォーマンスが向上します。

データベースにおけるJava(OJVM)により、Javaデータ・ロジックを使用してSQL操作をグループ化し、インプレース処理用にデータベースにロードできます。

この章では、Oracle Database 12cリリース2(12.2)とともにJDBCドライバ、ユニバーサル接続プール(UCP)およびデータベースにおけるJava(OJVM)について説明します

  • Java Database Connectivityドライバ(JDBC)
  • ユニバーサル接続プール(UCP)

  • データベースにおけるJava(OJVM)

Java Database Connectivityドライバ(JDBC)

JDBCは、ユーザーがデータベースに接続してSQL文を実行し、データベースに問合せできるようにするデータベース・アクセス・プロトコルです。JDBCドライバは、最新のJDBC仕様に準拠して実装されています。Javaアプリケーションは、クラスパスにJDK8と互換性のあるojdbc8.jarが必要です。

コアJavaクラス・ライブラリには、JDBC APIのjava.sqljavax.sqlが用意されています

次の項では、JDBC標準に対するOracleサポートについて説明します。

  • Oracle JDBC Thinドライバ

  • Oracle JDBCパッケージ

Oracle JDBC Thinドライバ

ほとんどの場合、JDBC Thinドライバを使用することをお薦めします。JDBC Thinドライバは、適切なJava仮想マシンを搭載したシステムであれば、どのシステム上でも機能します。(JVM)Oracleが提供する他のクライアント・ドライバとして、JDBC Thinドライバ、Oracle Call Interface (OCI)ドライバ、サーバー側Thinドライバ、サーバー側内部ドライバなどがあります。

JDBC Thinドライバは、Pure JavaのType IVドライバです。JDBCドライバ・バージョン(ojdbc8.jar)には、JDK 8のサポートが含まれています。

JDBC Thinドライバは、データベースにアクセスするためにSQL*Netを使用してサーバーと通信します。

関連項目:

『Oracle Database JDBC開発者ガイド』

アクション・アイテム1: DB_URLを変更してデータベースを指すようにします。ヘルプが必要な場合は、GithubのDataSourceSample.javaを参照してください。

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DatabaseMetaData;

import oracle.jdbc.pool.OracleDataSource;
import oracle.jdbc.OracleConnection;

public class DataSourceSample {  
  // The recommended format of a connection URL is the long format with the
  // connection descriptor.
  // final static String DB_URL= "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(HOST=myhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=myorcldbservicename)))";

  final static String DB_URL= "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(HOST=localhost)(PORT=5521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=service name)))";
  final static String DB_USER = "username";
  final static String DB_PASSWORD = password;

  public static void main (String args[]) throws SQLException {

    OracleDataSource ods = new OracleDataSource();
    ods.setURL(DB_URL);    
    ods.setUser(DB_USER);
    ods.setPassword(DB_PASSWORD);

    // With AutoCloseable, the connection is closed automatically.
    try (OracleConnection connection = (OracleConnection)  
      ods.getConnection()) {
      // Get the JDBC driver name and version 
      DatabaseMetaData dbmd = connection.getMetaData();       
      System.out.println("Driver Name: " + dbmd.getDriverName());
      System.out.println("Driver Version: " + 
        dbmd.getDriverVersion());
      System.out.println("Database Username is: " + 
        connection.getUserName());
    }   
  }
}

ユニバーサル接続プール

接続プールは、接続オブジェクトを再利用して、接続オブジェクトが作成される回数を減らすことで、パフォーマンスを向上させます。

Oracle Universal Connection Pool (UCP)は、Oracle Database構成との密接な統合を利用して、高可用性、スケーラビリティ、ロード・バランシングとともに接続プール機能を提供する、機能豊富なJava接続プールです。

UCPを使用するには、Javaアプリケーションまたはコンテナのクラスパスにucp.jarojdbc8.jar (JDK8)が必要です。

関連項目:

Oracle Universal Connection Pool開発者ガイド

アクション・アイテム2: DB_URLを変更してデータベースを指すようにします。

Import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import oracle.ucp.jdbc.PoolDataSourceFactory;
import oracle.ucp.jdbc.PoolDataSource;

public class UCPSample {
  // final static String DB_URL=   "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(HOST=myhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=myorcldbservicename)))";
 
  final static String DB_USER = "username";
  final static String DB_PASSWORD = "pwd";
  final static String CONN_FACTORY_CLASS_NAME = "oracle.jdbc.pool.OracleDataSource";

  /*
   * The sample demonstrates UCP as client side connection pool.
   */
  public static void main(String args[]) throws Exception {
    // Get the PoolDataSource for UCP
    PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();

    // Set the connection factory first before all other properties
    pds.setConnectionFactoryClassName(CONN_FACTORY_CLASS_NAME);
    pds.setURL(DB_URL);
    pds.setUser(DB_USER);
    pds.setPassword(DB_PASSWORD);
    pds.setConnectionPoolName("JDBC_UCP_POOL");

    // Default is 0. Set the initial number of connections to be 
    // created when UCP is started.
    pds.setInitialPoolSize(5);

    // Default is 0. Set the minimum number of connections
    // that is maintained by UCP at runtime.
    pds.setMinPoolSize(5);

    // Default is Integer.MAX_VALUE (2147483647). Set the maximum 
    // number of connections allowed on the connection pool.
    pds.setMaxPoolSize(20);

    // Default is 30secs. Set the frequency in seconds to enforce 
    // the timeout properties. Applies to    
    // inactiveConnectionTimeout(int secs),
    // AbandonedConnectionTimeout(secs)& 
    //TimeToLiveConnectionTimeout(int secs).
    // Range of valid values is 0 to Integer.MAX_VALUE.
    pds.setTimeoutCheckInterval(5);

    // Default is 0. Set the maximum time, in seconds, that a
    // connection remains available in the connection pool.
    pds.setInactiveConnectionTimeout(10);

    System.out.println("Available connections before checkout: "
        + pds.getAvailableConnectionsCount());
    System.out.println("Borrowed connections before checkout: "
        + pds.getBorrowedConnectionsCount());
    // Get the database connection from UCP.
    try (Connection conn = pds.getConnection()) {
      System.out.println("Available connections after checkout: "
          + pds.getAvailableConnectionsCount());
      System.out.println("Borrowed connections after checkout: "
          + pds.getBorrowedConnectionsCount());
      // Perform a database operation
      printEmployees(conn);
    } catch (SQLException e) {
      System.out.println("UCPSample - " + "SQLException occurred : "
          + e.getMessage());
    }
    System.out.println("Available connections after checkin: "
        + pds.getAvailableConnectionsCount());
    System.out.println("Borrowed connections after checkin: "
        + pds.getBorrowedConnectionsCount());
  }
 /*
  * Displays first_name and last_name from the employees table.
  */
  public static void printEmployees(Connection connection) 
     throws SQLException {
    // Statement and ResultSet are AutoCloseable and closed 
    // automatically. 
    try (Statement statement = connection.createStatement()) {      
      try (ResultSet resultSet = statement
          .executeQuery("select first_name, last_name from 
            employees")) {
        System.out.println("FIRST_NAME" + "  " + "LAST_NAME");
        System.out.println("---------------------");
        while (resultSet.next())
          System.out.println(resultSet.getString(1) + " "
              + resultSet.getString(2) + " ");       
      }
    }   
  } 
}

データベースにおけるJava(OJVM)

Oracle Databaseには、サーバーに常駐するJava仮想マシン(JVM)があります。それによって、サーバー上のOracle JVM内で実行中のJavaアプリケーションから、同じシステムおよび同じプロセスに存在するデータにアクセスできます。

データ処理が大きいアプリケーションには、データベースにおけるJavaをお薦めします。JVMは、基礎となるOracle RDBMSライブラリを直接使用する機能があり、JavaコードとSQLデータの間にネットワーク接続が必要ありません。そのため、パフォーマンスと実行が向上します。データ・アクセスのために、サーバー上でJavaコードを実行するとき、Oracle Databaseはサーバー側内部ドライバを使用します。

アクション・アイテム3: SQLPlusを介してデータベースに接続し、ServersideConnect.javaを起動する前にServersideConnect.sqlを実行します。詳細は、Githubのサンプルを参照してください。

ServersideConnect.sql


Rem NAME
Rem ServersideConnect.sql 
Rem
Rem DESCRIPTION
Rem SQL for invoking the method which gets a server side connection to
rem Reads the content of the Java source from ServersideConnect.java 
rem then compiles it 
connect username/pwd
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED ServersideConnect_src AS
@ ServersideConnect.java
/
show error
rem A wrapper (a.k.a. Call Spec), to invoke Java
rem function in the database from SQL, PL/SQL, and client applications
CREATE OR REPLACE PROCEDURE ServersideConnect_proc AS 
LANGUAGE JAVA NAME 'ServersideConnect.jrun ()';
/
rem running the sample
connect username/pwd
SET SERVEROUTPUT ON SIZE 10000 
CALL dbms_java.set_output (10000);

execute ServersideConnect_proc;


InternalT2Server.java
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import oracle.jdbc.driver.OracleDriver;
import oracle.jdbc.pool.OracleDataSource;

public class ServersideConnect {

  static public void jrun() throws SQLException {
    // For testing ServersideConnect
    // test("jdbc:oracle:kprb:@");
    method1("jdbc:default:connection");
    method2();
  }  
 /*
  * Shows using the server side Type 2 driver a.k.a KPRB driver 
  */ 
 static public void method1 (String url) throws SQLException {
    Connection connection = null; 
    try {
     // Method 1: Using OracleDataSource
      OracleDataSource ods = new OracleDataSource();
      ods.setURL(url);
      connection = ods.getConnection();
      System.out.println("Method 1: Getting Default Connection "
          + "using OracleDataSource");
      // Perform database operation
      printEmployees(connection);
    }
}

static public void method2 () throws SQLException {
   Connection connection = null; 
   try {
        OracleDriver ora = new OracleDriver();
        connection = ora.defaultConnection();
        System.out.println("Method 2: Getting Default Connection "
          + "using OracleDriver");
        // Perform database operation
        printEmployees(connection);
   }
}

 /*
  * Displays employee_id and first_name from the employees table.
  */
  static public void printEmployees(Connection connection) 
     throws SQLException {
    ResultSet resultSet = null;
    Statement statement = null;
    try {
      statement = connection.createStatement();
      resultSet = statement.executeQuery("SELECT employee_id, first_name" 
         +    " FROM employees order by employee_id");
      while (resultSet.next()) {
        System.out.println("Emp no: " + resultSet.getInt(1) + " Emp name: "
            + resultSet.getString(2));
      }
    }
    catch (SQLException ea) {
      System.out.println("Error during execution: " + ea);
      ea.printStackTrace();
    }
    finally {
      if (resultSet != null) resultSet.close();
      if (statement != null) statement.close();   
    }
  }
}