Spring BootでOracle DatabaseのPDB(Pluggable DataBase)に接続

nazology.net

⇧ amazing...

Oracle DatabaseのPDB(Pluggable DataBase)とは

Oracleのドキュメントによりますと、

docs.oracle.com

マルチテナント・アーキテクチャを使用すると、Oracle Databaseをマルチテナント・コンテナ・データベース(CDB)として機能させることができます。

https://docs.oracle.com/cd/E57425_01/121/CNCPT/cdbovrvw.htm

CDBは、顧客が作成した0以上のプラガブル・データベース(PDB)を含みます。PDBは、Oracle Netクライアントに非CDBとして表示されるスキーマスキーマ・オブジェクトおよび非スキーマ・オブジェクトの移植可能な集合ですOracle Database 12cまでのOracle Databaseはすべて非CDBでした。

https://docs.oracle.com/cd/E57425_01/121/CNCPT/cdbovrvw.htm

⇧ とあり、Oracle Database 12cで取り入れられた概念らしい。

そして、

docs.oracle.com

Oracle Database 20cから、マルチテナント・コンテナ・データベースがサポート対象の唯一のアーキテクチャになりました。前のリリースでは、Oracleは非コンテナ・データベース(非CDB)をサポートしていました。

https://docs.oracle.com/cd/F32587_01/cncpt/CDBs-and-PDBs.html#GUID-5C339A60-2163-4ECE-B7A9-4D67D3D894FB

Oracle Database 20cからは、マルチテナント・コンテナ・データベースのみの対応となったようです。

PDB(Pluggable DataBase)は、CDBに付属する形になってますと。

Spring BootでOracle DatabaseのPDB(Pluggable DataBase)に接続

で、ネットの情報を見てると、CDBとPDB(Pluggable DataBase)のどっちに接続するかを明示していない情報が多いんだけども、

learning-collection.com

⇧ 上記サイト様によりますと、PDB(Pluggable DataBase)に接続ということで良いようです。

ちなみに、今回、利用するのは、Oracle Database 19cになります。

ts0818.hatenablog.com

⇧ 上記の記事で作成していたテーブルを利用していきます。

とりあえず、テーブルにデータを入れておきます。

ちなみに、Oracleさん何を血迷ったか、

kanamelogic.com

注意点ですが、名前から日付のみを格納する型だと思われがちですが、時刻まで格納することができます。

DATE型、時刻を格納できることに注意 | かなめのロジック

⇧ ということで、中々の鬼畜仕様。Oracle Databaseを使う場合、生年月日にDate型を使わない方が良さそう、今回はDate型にしちゃってますが...。

■USERSテーブル

INSERT ALL
INTO USERS (user_id, insert_user, insert_date) VALUES (1, 'admin', CURRENT_TIMESTAMP)
INTO USERS (user_id, insert_user, insert_date) VALUES (2, 'admin', CURRENT_TIMESTAMP)
INTO USERS (user_id, insert_user, insert_date) VALUES (3, 'admin', CURRENT_TIMESTAMP)
SELECT * FROM DUAL;    

■USER_DETAILテーブル

INSERT ALL
INTO USER_DETAIL (user_id, last_name, first_name, gender, birthday, insert_user, insert_date, delete_flg) VALUES (1, '鈴木', '一郎', 'man', '1983-1-1', 'admin', CURRENT_TIMESTAMP, '0')
INTO USER_DETAIL (user_id, last_name, first_name, gender, birthday, insert_user, insert_date, delete_flg) VALUES (2, '佐藤', '二郎', 'man', '1982-2-1', 'admin', CURRENT_TIMESTAMP, '0')
INTO USER_DETAIL (user_id, last_name, first_name, gender, birthday, insert_user, insert_date, delete_flg) VALUES (3, '高橋', '三郎', 'man', '1981-3-1', 'admin', CURRENT_TIMESTAMP, '0')
SELECT * FROM DUAL;    

⇧ データが登録されました。

そしたらば、Eclipseを起動して、「ファイル(F)」>「新規(N)」>「Spring スターター・プロジェクト(Spring Initializr)」を選択。

ビルドツールは、Gradleにしたいので、「タイプ:」は「Gradle-Groovy」で。

依存関係を追加で。

依存関係ですが、

■/oracle-db-example/build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.5'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'com.oracle.database.jdbc:ojdbc11'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}    

oracle driverのバージョンを8から11に変えてます。

ちなみに、Oracle Databaseの場合、JDBCのURLの書き方が何種類かあるらしく、

qiita.com

⇧ 上記サイト様が詳しいです。

自分の場合、Oracle Database 12cと19cの2つインストールしてるせいか、リスナー名まで指定しないと情報が取得できなかったのですが、

⇧ サービス名を確認できますと。

Oracleのドキュメントによりますと、

docs.oracle.com

Thin-style service names are supported only by the JDBC Thin driver. The syntax is:

@//host_name:port_number/service_name

For example:

jdbc:oracle:thin:scott/tiger@//myhost:1521/myservicename

https://docs.oracle.com/cd/B28359_01/java.111/b31224/urls.htm#BEIDHCBA

⇧ サービス名を使う場合のURLは上記のようにするらしいですと。

というわけで、自分の環境ではポート番号とかも変えてるので、データベースの接続設定は以下のような感じになってます。

■/oracle-db-example/src/main/resources/application.properties

# DB接続情報
spring.datasource.url=jdbc:oracle:thin:@//localhost:1519/orcldb_19c
spring.datasource.username=ts0818
spring.datasource.password=password
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver

そしたらば、必要なクラスを作成していきます。

■/oracle-db-example/src/main/java/com/example/demo/entity/UserDetail.java

package com.example.demo.entity;

import java.time.LocalDate;
import java.time.OffsetDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;

@Data
@Entity
@Table(name="user_detail")
public class UserDetail {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="user_id")
	private String userId;
	
	@Column(name="last_name")
	private String lastName;
	
	@Column(name="first_name")
	private String firstName;
	
	@Column(name="gender")
	private String gender;
	
	@Column(name="birthday")
	private LocalDate birthday;
	
	@Column(name="address_id")
	private String addressId;
	
	@Column(name="insert_user")
	private String insertUser;
	
	@Column(name="insert_date")
	private OffsetDateTime insertDate;
	
	@Column(name="update_user")
	private String updateUser;
	
	@Column(name="update_date")
	private OffsetDateTime updateDate;
	
	@Column(name="delete_flg")
	private Character deleteFlg;
	
	@Column(name="delete_date")
	private OffsetDateTime deleteDate;
}

■/oracle-db-example/src/main/java/com/example/demo/repository/UserDetailRepository.java

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.demo.entity.UserDetail;

public interface UserDetailRepository extends JpaRepository<UserDetail, String> {

}    

■/oracle-db-example/src/main/java/com/example/demo/service/UserDetailServiceImpl.java

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.entity.UserDetail;
import com.example.demo.repository.UserDetailRepository;

@Service
public class UserDetailServiceImpl {
	@Autowired
	private UserDetailRepository userDetailRepository;
	
	public List<UserDetail> findAll() {
		return userDetailRepository.findAll();
	}
	
}    

■/oracle-db-example/src/main/java/com/example/demo/rest_controller/UserDetailController.java

package com.example.demo.rest_controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.entity.UserDetail;
import com.example.demo.service.UserDetailServiceImpl;

@RestController
public class UserDetailController {

	@Autowired
	private UserDetailServiceImpl userDetailServiceImpl;
	
	@GetMapping("find-all")
	public List<UserDetail> findAll() {
		return userDetailServiceImpl.findAll();
	}
	
}    

で、実行して、

ブラウザから、@RestControllerのメソッドのエンドポイントにアクセス。

Oracle DatabaseのPDB(Pluggable DataBase)に接続して、PDB(Pluggable DataBase)のテーブルから情報が取得できました。

Oracleのドキュメントに掲載されてるデータベースの接続情報が結構、適当なので何を信じて良いかがハッキリしない....

毎度モヤモヤ感が半端ない...

今回はこのへんで。