本ドキュメントでは、SpringDataJPAフレームワークとOceanBase Cloudデータベースを使用してアプリケーションを構築し、テーブルの作成、データの挿入、データのクエリなどの基本操作を実装する方法について説明します。
前提条件
- OceanBase Cloudデータベースアカウントを登録し、クラスタインスタンスとMySQL互換モードのテナントを作成していること。詳細は、クラスタインスタンスの作成およびテナントの作成をご参照ください。
- JDK 1.8およびMavenをインストールしていること。
- IntelliJ IDEAをインストールしていること。
説明
本ドキュメントでコードを実行するために使用しているツールはIntelliJ IDEA 2021.3.2 (Community Edition)ですが、好みに応じて適切なツールを選択してサンプルコードを実行することもできます。
操作手順
説明
本ドキュメントに記載されている手順は、Windows環境に基づいています。他のオペレーティングシステム環境やコンパイラを使用している場合、手順が若干異なる場合があります。
- OceanBase Cloudデータベースの接続文字列を取得します。
java-oceanbase-springdatajpaプロジェクトをIDEAにインポートします。java-oceanbase-springdatajpaプロジェクト内のデータベース接続情報を変更します。java-oceanbase-springdatajpaプロジェクトを実行します。
操作手順1:OceanBase Cloudデータベースの接続文字列の取得
OB Cloudクラウドデータベースコンソールにログインします。インスタンスリストページで対象インスタンスの情報を展開し、対象テナントの下で 接続 > 接続文字列を取得 を選択します。
詳細な操作については、接続文字列の取得をご参照ください。
作成済みのOceanBase Cloudデータベースに基づいて、以下のURLの対応する情報を入力します。
説明
application.ymlファイルでこのURL情報が必要になります。jdbc:oceanbase://host:port/schema_name?user=$user_name&password=$password&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8パラメータの説明:
host:OceanBase Cloudデータベースの接続アドレスを指定します。例:t********.********.oceanbase.cloud。port:OceanBase Cloudデータベースの接続ポートを指定します。デフォルトは3306です。schema_name:アクセスするスキーマ名。user_name:データベースにアクセスするアカウントを指定します。password:アカウントのパスワードを指定します。characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8:追加の接続属性です。characterEncoding:データベースURLオプションでサポートされる文字エンコーディング。デフォルト値はutf8です。useSSL:接続時にSSL/TLSの使用を強制するかどうか。デフォルト値はfalseです。serverTimezone:サーバーのタイムゾーンを設定します。デフォルト値は中国標準時です。
URLパラメータの詳細については、データベースURLをご参照ください。
操作手順2:java-oceanbase-springdatajpa プロジェクトのIDEAへのインポート
IntelliJ IDEA を開き、File > Open... オプションを選択します。
ポップアップ表示される Open File or Project ウィンドウで、対応するプロジェクトファイルを選択し、OK をクリックしてプロジェクトファイルのインポートを完了します。
IntelliJ IDEAはプロジェクト内の各種ファイルを自動的に認識し、Project ツールウィンドウでプロジェクトのディレクトリ構造、ファイルリスト、モジュールリスト、依存関係などの情報を確認できます。Project ツールウィンドウは通常、IntelliJ IDEAインターフェースの左端にあり、デフォルトでは開いています。Project ツールウィンドウが閉じている場合は、メニューバーの View > Tool Windows > Project をクリックするか、ショートカットキー Alt + 1 を使用して再度開くことができます。
説明
IntelliJ IDEAを使用してプロジェクトをインポートすると、IntelliJ IDEAはプロジェクト内のpom.xmlファイルを自動的に検出し、ファイルに記述された依存関係に基づいて必要な依存ライブラリを自動的にダウンロードしてプロジェクトに追加します。
プロジェクトの状況を確認します。
操作手順3:java-oceanbase-springdatajpa プロジェクト内のデータベース接続情報の変更
手順1:OceanBase Cloudデータベースの接続文字列の取得 の情報に基づいて、application.yml ファイル内のデータベース接続情報を変更します。
例:
- データベースドライバ名:
com.mysql.cj.jdbc.Driver - OBServerノードのIPアドレス:
t5******.********.oceanbase.cloud - アクセスポート:3306
- アクセスするスキーマ名:
test - テナントの接続アカウント:
mysql001 - パスワード:
******
サンプルコードは以下の通りです:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://t5******.********.oceanbase.cloud:3306/test?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: mysql001
password: ******
type: com.alibaba.druid.pool.DruidDataSource
操作手順4:java-oceanbase-springdatajpa プロジェクトの実行
実行パス
- プロジェクト構造の src > test > java から
TestSpringDataJpaApplicationTests.javaファイルを見つけます。 - ツールメニューバーで Run > Run... > TestSpringDataJpaApplicationTests.contextLoads を選択するか、右上の緑色の三角形を直接クリックして実行します。
- IDEAのコンソールからプロジェクトのログ情報と出力結果を確認します。
実行結果
User{id=1, username='insert1'}
User{id=2, username='update'}
User{id=3, username='insert3'}
User{id=4, username='insert4'}
User{id=5, username='insert5'}
よくある質問
1. 接続タイムアウト
接続タイムアウトの問題が発生した場合は、JDBC URLで接続タイムアウトパラメータを設定できます:
jdbc:mysql://host:port/database?connectTimeout=30000&socketTimeout=60000
2. 文字セットの問題
正しい文字エンコーディングを確保するために、JDBC URLで正しい文字セットパラメータを設定します:
jdbc:mysql://host:port/database?characterEncoding=utf8&useUnicode=true
3. SSL接続
OceanBase CloudデータベースとのSSL接続を有効にするには、JDBC URLに以下のパラメータを追加します:
jdbc:mysql://host:port/database?useSSL=true&requireSSL=true
4. アカウントパスワード内の特殊文字
ユーザー名またはパスワードに特殊文字(#など)が含まれている場合は、URLエンコードを行う必要があります:
String encodedPassword = URLEncoder.encode(password, "UTF-8");
注意
MySQL Connector/J 8.xを使用する場合、アカウントパスワードにハッシュ記号(#)が含まれていないことを確認してください。含まれていると、接続エラーが発生する可能性があります。
プロジェクトコードの紹介
java-oceanbase-springdatajpa をクリックしてプロジェクトコードをダウンロードします。これは java-oceanbase-springdatajpa という名前の圧縮パッケージです。
解凍すると、java-oceanbase-springdatajpa という名前のフォルダが生成されます。ディレクトリ構造は以下の通りです:
│--pom.xml
│
├─.idea
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─oceanbase
│ │ │ └─testspringdatajpa
│ │ │ │--TestSpringDataJpaApplication.java
│ │ │ │
│ │ │ ├─dao
│ │ │ │ └─UserRepository.java
│ │ │ │
│ │ │ ├─entity
│ │ │ │ └─User.java
│ │ │ │
│ │ │ └─service
│ │ │ │--UserService.java
│ │ │ │
│ │ │ └─impl
│ │ │ └─--UserServiceImpl.java
│ │ │
│ │ └─resources
│ │ │--application.yml
│ │ │
│ │ ├─static
│ │ └─templates
│ └─test
│ └─java
│ └─com
│ └─oceanbase
│ └─testspringdatajpa
│ └─--TestSpringDataJpaApplicationTests.java
│
└─target
ファイルの説明:
pom.xml:Mavenプロジェクトの設定ファイル。プロジェクトの依存関係、プラグイン、ビルドなどの情報が含まれます。.idea:IDE(統合開発環境)で使用されるディレクトリ。プロジェクト関連の設定情報を保存します。src:通常、プロジェクト内のソースコードを格納するディレクトリを表します。main:主要なソースコードとリソースファイルを格納するディレクトリ。java:Javaソースコードを格納するディレクトリ。com:Javaパッケージのルートディレクトリ。oceanbase:プロジェクトのルートディレクトリ。testspringdatajpa:Javaパッケージのルートディレクトリ。プロジェクトのすべてのJavaクラスが含まれます。TestSpringDataJpaApplication.java:Spring Bootアプリケーションのエントリクラス。dao:データアクセスオブジェクト(Data Access Object)パッケージを格納し、データベースやその他のデータストレージサービスへのアクセスに使用されます。UserRepository.java:ユーザーデータアクセスインターフェース。ユーザーデータの追加、削除、変更、クエリ操作を定義します。entity:エンティティクラスのディレクトリ。データベーステーブルに対応するJavaクラスを格納します。User.java:ユーザー永続化オブジェクト。ユーザーデータテーブルのフィールドをマッピングします。service:サービスインターフェースディレクトリ。ビジネスロジックインターフェースを定義します。UserService.java:ユーザーサービスインターフェース。ユーザーデータに対する操作メソッドを定義します。impl:サービス実装ディレクトリ。ビジネスロジックの実装クラスを格納します。UserServiceImpl.java:ユーザーサービスの実装クラス。UserServiceインターフェースで定義されたメソッドを実装します。resources:設定ファイルやSQLファイルなどのリソースファイルを格納するディレクトリ。application.yml:アプリケーションの設定ファイル。データベース接続などの情報を設定します。static:CSSやJavaScriptなどの静的ファイルを格納します。templates:HTMLテンプレートなどのテンプレートファイルを格納します。test:テストコードとリソースファイルを格納するディレクトリ。TestSpringDataJpaApplicationTests.java:Spring Data JPAに関連する機能の実行と検証に使用されるクラスを格納します。target:コンパイル後のClassファイルやJarパッケージなどのファイルを格納するディレクトリ。
pom.xml コードの紹介
説明
サンプルを検証するだけであれば、デフォルトのコードを使用し、変更する必要はありません。以下の説明に従って、要件に応じて pom.xml ファイルを変更することもできます。
pom.xml 設定ファイルの内容は以下の通りです:
ファイル宣言文。
このファイルがXMLファイルであり、使用するXMLバージョンが
1.0、文字エンコーディングがUTF-8であることを宣言します。コードは以下の通りです:
<?xml version="1.0" encoding="UTF-8"?>POMの名前空間とPOMモデルバージョンを設定します。
xmlnsを使用して、POMの名前空間をhttp://maven.apache.org/POM/4.0.0。` に指定します。xmlns:xsiを使用して、XML名前空間をhttp://www.w3.org/2001/XMLSchema-instance。` に指定します。xsi:schemaLocationを使用して、POMの名前空間をhttp://maven.apache.org/POM/4.0.0,并指定、POMのXSDファイルの場所を に指定し、POMのXSDファイルの場所をhttps://maven.apache.org/xsd/maven-4.0.0.xsd` に指定します。<modelVersion>要素を使用して、このPOMファイルで使用されるPOMモデルバージョンを4.0.0に指定します。
コードは以下の通りです:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>親プロジェクトの情報を設定します。
<groupId>を使用して、親プロジェクトの識別子をorg.springframework.bootに指定します。<artifactId>を使用して、親プロジェクトの依存関係をspring-boot-starter-parentに指定します。<version>を使用して、親プロジェクトのバージョン番号を2.7.0に指定します。relativePathを使用して、親プロジェクトのパスが空であることを示します。
コードは以下の通りです:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> <relativePath/> </parent>基本情報を設定します。
<groupId>を使用して、プロジェクトの識別子をcom.oceanbaseに指定します。<artifactId>を使用して、プロジェクトの依存関係をjava-oceanbase-springdatajpaに指定します。<version>を使用して、プロジェクトのバージョン番号を0.0.1-SNAPSHOTに指定します。descriptionを使用して、プロジェクト情報をDemo project for Spring Bootとして紹介します。
コードは以下の通りです:
<groupId>com.oceanbase</groupId> <artifactId>java-oceanbase-springdatajpa</artifactId> <version>0.0.1-SNAPSHOT</version> <name>java-oceanbase-springdatajpa</name> <description>Demo project for Spring Boot</description>Javaバージョンを設定します。
プロジェクトで使用するJavaバージョンを1.8に指定します。
コードは以下の通りです:
<properties> <java.version>1.8</java.version> </properties>コア依存関係を設定します。
依存関係が属する組織を
org.springframework.boot、名前をspring-boot-starter-data-jpaに指定します。この依存ライブラリには、JPAを使用したデータアクセスに必要な依存関係と設定が含まれており、Spring Boot Starter Data JPAはSpring Bootのスターターです。コードは以下の通りです:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>依存関係が属する組織を
org.springframework.boot、名前をspring-boot-starter-webに指定します。この依存ライブラリには、Spring Bootを使用したWeb開発に必要な依存関係と設定が含まれており、Spring Bootのスターターです。コードは以下の通りです:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>依存関係が属する組織を
org.springframework.boot、名前をspring-boot-starter-test、スコープをtestに指定します。この依存関係により、JUnit、Mockito、Hamcrestなど、Spring Bootが提供するテストフレームワークとツールを使用できます。コードは以下の通りです:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>依存関係が属する組織を
com.alibaba、名前をdruid、バージョン番号を1.2.8に指定します。この依存関係により、Druidライブラリを使用して、データベース接続の取得と解放を管理および最適化できます。コードは以下の通りです:
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency>依存関係が属する組織を
com.oceanbase、名前をoceanbase-client、バージョン番号を2.4.2に指定します。この依存関係により、接続、クエリ、トランザクションなど、OceanBaseが提供するクライアント機能を使用できます。コードは以下の通りです:
<dependencies> <dependency> <groupId>com.oceanbase</groupId> <artifactId>oceanbase-client</artifactId> <version>2.4.2</version> </dependency> </dependencies>
Mavenプラグインを設定します。
依存関係が属する組織を
org.springframework.boot、名前をspring-boot-maven-pluginに指定します。このプラグインは、Spring Bootアプリケーションを実行可能なJARパッケージまたはWARパッケージにパッケージ化し、直接実行できるようにするために使用されます。他のプラグインやツールとの競合を避けるため、ビルドプロセスでLombokの依存関係を除外します。コードは以下の通りです:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>
application.yml コードの紹介
application.yml ファイルはSpring Bootアプリケーションの設定ファイルであり、いくつかの重要なパラメータが含まれています。アプリケーションのコンテキストパス、リスニングポート番号、データベース接続情報、およびJPA関連の属性を設定します。
application.yml ファイルのコードは、主に以下の部分で構成されています:
Server部分servlet:Servlet関連の属性を設定するために使用されます。context-path:アプリケーションのコンテキストパスをtestspringdatajpaに指定します。port:アプリケーションがリスニングするポート番号を8890に指定します。
コードは以下の通りです:
server: servlet: context-path: /testspringdatajpa port: 8890Spring部分datasource:データソース関連の属性、つまりデータベース接続情報を設定するために使用されます。driver-class-name:データベースドライバのクラス名をcom.mysql.cj.jdbc.Driverに指定します。url:データベースのアドレス、ポート番号、データベース名などの情報を含む、データベースの接続URLを指定します。username:データベースに接続するユーザー名を指定します。password:データベースに接続するパスワードを指定します。type:データソースとしてDruid接続プールを使用するように指定します。
コードは以下の通りです:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://host:port/schema_name?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8 username: user_name password: ****** type: com.alibaba.druid.pool.DruidDataSource
* `JPA` 部分
* `hibernate`:Hibernate関連の属性を設定するために使用されます。
* `ddl-auto`:起動時にHibernateがデータベース構造を自動的に更新するように `update` を指定します。
* `show-sql`:コンソールにSQL文を出力するかどうかを指定します。値は `true` です。
* `format-sql`:出力されるSQL文をフォーマットするかどうかを指定します。値は `true` です。
* `open-in-view`:`Open-in-View` モードを有効にするかどうかを指定します。値は `false` です。
**コードは以下の通りです:**
```yml
jpa:
hibernate:
ddl-auto: update
show-sql: true
format-sql: true
open-in-view: false
```
### userRepository.java ファイルの紹介
`userRepository.java` ファイルは、DAOインターフェースを通じてユーザーエンティティ(User)に対するデータベース操作メソッドを定義するために使用されます。カスタムの更新およびクエリメソッドが含まれており、SQL文とHQL文を使用して操作を行います。
`userRepository.java` ファイルのコードは、主に以下の部分で構成されています:
1. 他のクラスとインターフェースの参照。
現在のファイルに以下のインターフェースとクラスが含まれていることを宣言します:
* `User` クラス:サービスクラスでユーザーオブジェクトを操作および処理するために使用されます。
* `JpaRepository` インターフェース:このインターフェースを継承して基本的なCRUD操作メソッドを取得するために使用されます。
* `Modifying` アノテーション:変更操作のメソッドをマークするために使用されます。
* `Query` アノテーション:カスタムクエリメソッドを定義するために使用されます。
* `Param` アノテーション:メソッドのパラメータをクエリ文のパラメータにマッピングするために使用されます。
* `Repository` アノテーション:DAOインターフェースをSpringのリポジトリコンポーネントとしてマークするために使用されます。
**コードは以下の通りです:**
```java
import com.oceanbase.testspringdatajpa.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
```
2. `UserRepository` インターフェースの定義。
`UserRepository` インターフェースはユーザーデータへのアクセスに使用されます。Springの `Repository` コンポーネントとしてマークされ、`bean` の名前を `userRepository` に指定します。
1. `@Query` アノテーションを使用してSQL文を指定し、`nativeQuery = true` を使用してネイティブSQL文を使用します。
2. `@Modifying` アノテーションを使用してカスタム更新メソッドを定義し、ネイティブSQL文を使用して更新操作を行います。
3. `@Query` アノテーションを使用してHQL(Hibernate Query Language)文を指定し、`@Param` アノテーションを使用してメソッドのパラメータをHQL文のパラメータにマッピングします。
**コードは以下の通りです:**
```java
@Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Integer> {
@Query(value = "update test_springdatajpa_2 set username=?1 where id=?2", nativeQuery = true)
@Modifying
int updateById(String name, String id);
@Query("SELECT u FROM User u WHERE u.username = :username")
User findUser(@Param("username") String username);
}
```
### User.java ファイルの紹介
`User.java` ファイルは、Userクラスを定義することでユーザーオブジェクトを表すために使用されます。
`User.java` ファイルのコードは、主に以下の部分で構成されています:
1. 他のクラスのインポート。
`javax.persistence.*`: `javax.persistence` パッケージ内のすべてのクラスをインポートするために使用されます。`javax.persistence` はJava Persistence API(JPA)の標準パッケージであり、オブジェクト関係マッピング(ORM)を行うためのインターフェースとアノテーションのセットを提供します。
**コードは以下の通りです:**
```java
import javax.persistence.*;
```
2. `User` オブジェクトの定義。
JPAアノテーションを使用して、テーブル名、主キー、フィールド名など、エンティティクラスとテーブルのマッピング関係を識別します。
`@Entity` アノテーションでこのクラスをエンティティクラスとしてマークし、`@Table` アノテーションで対応するデータベーステーブル名を指定し、`@Id` アノテーションでエンティティクラスの主キーをマークし、`@GeneratedValue` アノテーションで主キーの生成戦略を指定し、`@Column` アノテーションでフィールド名と制約条件を指定します。このクラスには `id` と `username` の2つの属性があり、それぞれユーザーの一意の識別子とユーザー名を表します。また、空の `User` オブジェクトを作成するためのデフォルトコンストラクタも提供されています。
**コードは以下の通りです:**
```java
@Entity
@Table(name = "test_springdatajpa_2")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username")
private String username;
public User() {
}
}
```
3. `id` と `name` の値の取得と設定。
このエンティティクラスは、エンティティクラスオブジェクトを作成し、`id` と `username` 属性を初期化するためのパラメータ付きコンストラクタを提供します。
`id` と `name` 属性の値を取得および設定するための4つのメソッドを定義します。
* `getId` メソッドは `id` の値を取得するために使用されます。
* `setId` メソッドは `id` の値を設定するために使用されます。
* `getName` メソッドはユーザー名 `name` の値を取得するために使用されます。
* `setName` メソッドはユーザー名 `name` の値を設定するために使用されます。
**コードは以下の通りです:**
```java
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
```
4. `User` オブジェクトの文字列表現を返します。
`User` クラスの `toString` メソッドをオーバーライドし、`User` オブジェクトの文字列表現を返すために使用します。
`@Override` を定義して、親クラスの同名メソッドをオーバーライドします。`toString` メソッドを定義し、`User` オブジェクトの文字列表現を返すために使用します。文字列の連結により、`id` と `name` 属性の値を文字列としてフォーマットし、呼び出し元に `User` を返します。
**コードは以下の通りです:**
```java
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
```
### UserServiceImpl.java ファイルの紹介
`UserServiceImpl.java` ファイルは、JPAを使用してデータベースを操作し、ユーザーデータの追加、削除、変更、クエリを行います。
`UserServiceImpl.java` ファイルのコードは、主に以下の部分で構成されています:
1. 他のクラスとインターフェースの参照。
現在のファイルに以下のインターフェースとクラスが含まれていることを宣言します:
* `UserRepository` クラス:サービスクラスに注入し、データアクセスオブジェクト(DAO)で定義されたメソッドを呼び出すために使用されます。
* `User` クラス:サービスクラスでユーザーオブジェクトを操作および処理するために使用されます。
* `UserService` クラス:他のクラスに注入し、サービスクラスで定義されたメソッドを呼び出すために使用されます。
* `Autowired` アノテーション:依存オブジェクトを自動的に注入するために使用されます。
* `Page` クラス:ページネーションクエリ結果のカプセル化に使用されます。
* `PageRequest` クラス:ページネーションリクエストオブジェクトの作成に使用されます。
* `Pageable` インターフェース:ページネーションリクエストのインターフェースを定義するために使用されます。
* `Sort` クラス:ソート規則を定義するために使用されます。
* `Service` アノテーション:クラスをサービスクラスとしてマークするために使用されます。
* `Transactional` アノテーション:トランザクションメソッドをマークするために使用されます。
* `Iterator` クラス:コレクションを反復処理するために使用されます。
* `Optional` クラス:nullになる可能性のあるオブジェクトを処理するために使用されます。
**コードは以下の通りです:**
```java
import com.oceanbase.testspringdatajpa.dao.UserRepository;
import com.oceanbase.testspringdatajpa.entity.User;
import com.oceanbase.testspringdatajpa.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.Optional;
```
2. `UserServiceImpl` クラスは、`UserService` インターフェースで宣言されたメソッドを実装します。
依存関係の注入により `UserRepository` を使用してデータベースへのアクセスを実現します。具体的には、ユーザーデータの挿入、削除、更新、クエリのメソッドを実装し、ページネーションクエリをサポートします。`@Transactional` アノテーションを使用してトランザクションサポートを有効にし、データベース操作がトランザクション内で実行されるようにします。
1. `UserRepository` 属性の構築。
プライベートな `UserRepository` 属性を定義し、コンストラクタで `@Autowired` アノテーションを使用して依存関係を注入します。コンストラクタを通じて `UserRepository` の依存関係を注入し、`userRepository` 属性を使用してユーザーデータにアクセスおよび操作します。
**コードは以下の通りです:**
```java
private final UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
```
2. ユーザーデータの挿入。
`insertUser` メソッドで `User` オブジェクトをパラメータとして受け取り、`UserRepository` の `save` メソッドを呼び出して、ユーザーオブジェクトをデータベースに保存します。
**コードは以下の通りです:**
```java
@Override
public void insertUser(User user) { userRepository.save(user); }
```
3. ユーザーデータの削除。
`deleteUser` メソッドで、`UserRepository` の `existsById` メソッドを呼び出して指定されたidのユーザーが存在するかどうかを判断し、存在する場合は削除操作を行い、存在しない場合はそのまま戻ります。
**コードは以下の通りです:**
```java
@Override
public void deleteUser(Integer id) {
if (!userRepository.existsById(id)) {
return;
}
}
```
4. ユーザーデータの変更。
`updateUser` メソッドで、`UserRepository` の `save` メソッドを呼び出してユーザーオブジェクトをデータベースに保存し、更新操作を実現します。同時に、更新操作が成功したことを示す整数値 `1` を返します。
また、ユーザー名と `id` に基づいてユーザーデータを更新するメソッドもあり、`UserRepository` の `updateById` メソッドを呼び出して更新操作を実現し、更新結果を返します。
**コードは以下の通りです:**
```java
@Override
public int updateUser(User user) {
userRepository.save(user);
return 1;
}
//update based on name and id
@Override
public int updateUserById(String name, String id) {
return userRepository.updateById(name, id);
}
```
5. ユーザーデータのクエリ。
1. `ID` に基づくユーザーデータのクエリ。
`selectUserById` メソッドで、`UserRepository` の `findById` メソッドを呼び出してユーザーデータをクエリし、結果を `Optional` オブジェクトとしてカプセル化します。次に、`Optional` の `orElse` メソッドを呼び出して `Optional` オブジェクト内の値を取得し、それを `user` 変数に代入します。最後に、クエリされたユーザーオブジェクトを返します。
2. ユーザー名に基づくユーザーデータのクエリ。
`selectUserByName` メソッドで、`UserRepository` の `findUser` メソッドを呼び出してユーザー名に基づいてユーザーデータをクエリし、クエリされたユーザーオブジェクトを直接返します。
**コードは以下の通りです:**
```java
@Override
public User selectUserById(Integer id) {
Optional<User> optional = userRepository.findById(id);
User user = optional.orElse(null);
return user;
}
@Override
public User selectUserByName(String username) {
return userRepository.findUser(username);
}
```
6. すべてのユーザーデータのページネーションクエリ。
`selectUserAll` メソッドで、`Sort` オブジェクトを作成してソート規則を指定し、`Pageable` オブジェクトを作成してページネーションパラメータを指定し、`UserRepository` の `findAll` メソッドを呼び出してユーザーデータをクエリし、`Page` オブジェクトを返します。次に、`Page` オブジェクトの `iterator` メソッドを呼び出して、ユーザーデータのイテレータを取得します。最後に、ユーザーデータのイテレータを返します。
**コードは以下の通りです:**
```java
@Override
public Iterator<User> selectUserAll(Integer pageNum, Integer pageSize) {
Sort sort = Sort.by(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(pageNum, pageSize, sort);
Page<User> users = userRepository.findAll(pageable);
Iterator<User> userIterator = users.iterator();
return userIterator;
}
```
### UserService.java ファイルの紹介
`UserService.java` ファイルは、JPAを使用してデータベースを操作し、ユーザーデータの追加、削除、変更、クエリを行います。
`UserService.java` ファイルのコードは、主に以下の部分で構成されています:
1. 他のクラスとインターフェースの参照。
現在のファイルに以下のクラスが含まれていることを宣言します:
* `User` クラス:サービスクラスでユーザーオブジェクトを操作および処理するために使用されます。
* `Iterator` クラス:コレクションを反復処理するために使用されます。
**コードは以下の通りです:**
```java
import com.oceanbase.testspringdatajpa.entity.User;
import java.util.Iterator;
```
2. `UserService` インターフェースの定義。
`UserService` インターフェースを通じて、ユーザーデータの挿入、削除、更新、クエリを行うメソッドを定義します。以下のメソッドとクラスが含まれます:
* `insertUser` メソッド:ユーザーデータを挿入するために使用されます。
* `deleteUser` メソッド:ユーザーデータを削除するために使用されます。
* `updateUser` メソッド:ユーザーデータを更新するために使用されます。
* `updateUserById` メソッド:`id` に基づいてユーザーの `name` を変更するために使用されます。
* `selectUserById` メソッド:`id` に基づいてユーザーデータをクエリするために使用されます。
* `selectUserByName` メソッド:ユーザー名に基づいてユーザーデータをクエリするために使用されます。
* `selectUserAll` メソッド:すべてのユーザーデータをページネーションクエリするために使用されます。
* `User` クラス:サービスクラスでユーザーオブジェクトを操作および処理するために使用されます。
* `Iterator` クラス:コレクションを反復処理するために使用されます。
**コードは以下の通りです:**
```java
public interface UserService {
//insert
void insertUser(User user);
//delete
void deleteUser(Integer id);
//update
int updateUser(User user);
//customize SQL and modify name based on id
int updateUserById(String name, String id);
//select one user
User selectUserById(Integer id);
//customize SQL to query users based on username
User selectUserByName(String username);
//query all users
Iterator<User> selectUserAll(Integer pageNum, Integer pageSize);
}
```
### TestSpringDataJpaApplication.java ファイルの紹介
`TestSpringDataJpaApplication.java` ファイルは、Spring Bootアプリケーションの起動と設定に使用されます。
`TestSpringDataJpaApplication.java` ファイルのコードは、主に以下の部分で構成されています:
1. クラスとインターフェースの定義。
現在のファイルに以下のクラスが含まれていることを宣言します:
* `SpringApplication` クラス:Spring Bootアプリケーションを起動するために使用されます。
* `@SpringBootApplication` アノテーション:Spring Bootアプリケーションのエントリクラスをマークするために使用されます。
**コードは以下の通りです:**
```java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
```
2. `TestSpringDataJpaApplication` クラスの定義。
`@SpringBootApplication` アノテーションを使用してSpring Bootアプリケーションのエントリクラスを識別し、`main` メソッドで `SpringApplication.run` メソッドを呼び出してアプリケーションを起動します。
**コードは以下の通りです:**
```java
@SpringBootApplication
public class TestSpringDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringDataJpaApplication.class, args);
}
}
```
### TestSpringDataJpaApplicationTests.java ファイルの紹介
`TestSpringDataJpaApplicationTests.java` ファイルは、Spring Bootアプリケーションの起動と設定に使用されます。
`TestSpringDataJpaApplicationTests.java` ファイルのコードは、主に以下の部分で構成されています:
1. 他のクラスとインターフェースの参照。
現在のファイルに以下のクラスが含まれていることを宣言します:
* `User` クラス:サービスクラスでユーザーオブジェクトを操作および処理するために使用されます。
* `UserService` クラス:他のクラスに注入し、サービスクラスで定義されたメソッドを呼び出すために使用されます。
* `@Test` アノテーション:テストメソッドをマークするために使用されます。
* `Autowired` アノテーション:依存オブジェクトを自動的に注入するために使用されます。
* `@SpringBootTest` アノテーション:Spring Bootアプリケーションをテストするために使用されます。
* `Iterator` クラス:コレクションを反復処理するために使用されます。
**コードは以下の通りです:**
```java
import com.oceanbase.testspringdatajpa.entity.User;
import com.oceanbase.testspringdatajpa.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Iterator;
```
2. `UserService` メソッドの定義。
Spring Bootアプリケーション内の `UserService` サービスの各メソッドをテストするために使用されます。`UserService` の依存関係を注入し、各メソッドを呼び出してユーザーデータの挿入、削除、更新、クエリの機能をテストし、関連する結果を出力します。
1. `@Autowired` アノテーションを使用します。
`UserService` インターフェースの実装クラスを `userService` 変数に自動的に注入します。
**コードは以下の通りです:**
```java
@Autowired
private UserService userService;
```
2. `contextLoads` メソッドを使用してテストします。
1. ユーザーデータの挿入。
`for` ループを使用して、`userService` の `insertUser` メソッドを呼び出し、10個のユーザーデータを挿入します。
**コードは以下の通りです:**
```java
for (int i = 1; i <= 10; i++) {
userService.insertUser(new User(i, "insert" + i));
}
```
2. ユーザーデータの削除。
`userService` の `deleteUser` メソッドを呼び出し、idが1のユーザーデータを削除します。
**コードは以下の通りです:**
```java
userService.deleteUser(1);
```
3. ユーザーデータの変更。
`userService` の `updateUser` メソッドを呼び出し、idが2のユーザーデータを更新します。
**コードは以下の通りです:**
```java
userService.updateUser(new User(2, "update"));
```
4. ユーザーデータのクエリ。
* `userService` の `selectUserById` メソッドを呼び出し、idに基づいてユーザーデータをクエリし、結果を `user` 変数に代入します。`user` オブジェクトを出力します。
* `userService` の `selectUserByName` メソッドを呼び出し、ユーザー名に基づいてユーザーデータをクエリし、結果を `userByName` 変数に代入します。`userByName` オブジェクトを出力します。
**コードは以下の通りです:**
```java
User user = userService.selectUserById(2);
System.out.println("user = " + user);
User userByName = userService.selectUserByName("insert");
System.out.println("userByName = " + userByName);
```
5. ユーザーデータのページネーションクエリ。
`userService` の `selectUserAll` メソッドを呼び出し、すべてのユーザーデータをページネーションクエリし、結果を `userIterator` 変数に代入します。`forEachRemaining` メソッドを使用して `userIterator` を反復処理し、各ユーザーオブジェクトを出力します。
**コードは以下の通りです:**
```java
Iterator<User> userIterator = userService.selectUserAll(0, 5);
userIterator.forEachRemaining(System.out::println);
```
### 完全なコードの表示
:::tab
tab pom.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.oceanbase</groupId>
<artifactId>java-oceanbase-springdatajpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>java-oceanbase-springdatajpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>com.oceanbase</groupId>
<artifactId>oceanbase-client</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
```
tab application.yml
```yml
server:
servlet:
context-path: /testspringdatajpa
port: 8890
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:oceanbase://host:port/schema_name?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: user_name
password: ******
type: com.alibaba.druid.pool.DruidDataSource
jpa:
hibernate:
ddl-auto: update
show-sql: true
format-sql: true
open-in-view: false
```
tab userRepository.java
```java
package com.oceanbase.testspringdatajpa.dao;
import com.oceanbase.testspringdatajpa.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Integer> {
//Custom repository handwritten SQL, placeholder value transfer form
@Query(value = "update test_springdatajpa_2 set username=?1 where id=?2", nativeQuery = true)
@Modifying
int updateById(String name, String id);
//SPEL expression, hql syntax
@Query("SELECT u FROM User u WHERE u.username = :username")
User findUser(@Param("username") String username);//Mapping parameter username to database field username
}
tab User.java
package com.oceanbase.testspringdatajpa.entity;
import javax.persistence.*;
@Entity
@Table(name = "test_springdatajpa_2")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username")
private String username;
public User() {
}
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
}
tab UserServiceImpl.java
package com.oceanbase.testspringdatajpa.service.impl;
import com.oceanbase.testspringdatajpa.dao.UserRepository;
import com.oceanbase.testspringdatajpa.entity.User;
import com.oceanbase.testspringdatajpa.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.Optional;
@Transactional
@Service("userService")
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
//insert
@Override
public void insertUser(User user) { userRepository.save(user); }
//delete
@Override
public void deleteUser(Integer id) {
if (!userRepository.existsById(id)) {
return;
}
}
//update
@Override
public int updateUser(User user) {
userRepository.save(user);
return 1;
}
//update based on name and id
@Override
public int updateUserById(String name, String id) {
return userRepository.updateById(name, id);
}
// select one user
@Override
public User selectUserById(Integer id) {
Optional<User> optional = userRepository.findById(id);
User user = optional.orElse(null);
return user;
}
//query user based on username
@Override
public User selectUserByName(String username) {
return userRepository.findUser(username);
}
@Override
public Iterator<User> selectUserAll(Integer pageNum, Integer pageSize) {
//By passing parameters to this method, physical pagination can be achieved, which is very simple.
Sort sort = Sort.by(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(pageNum, pageSize, sort);
Page<User> users = userRepository.findAll(pageable);
Iterator<User> userIterator = users.iterator();
return userIterator;
}
}
tab UserService.java
package com.oceanbase.testspringdatajpa.service;
import com.oceanbase.testspringdatajpa.entity.User;
import java.util.Iterator;
public interface UserService {
//insert
void insertUser(User user);
//delete
void deleteUser(Integer id);
//update
int updateUser(User user);
//customize SQL and modify name based on id
int updateUserById(String name, String id);
//select one user
User selectUserById(Integer id);
//customize SQL to query users based on username
User selectUserByName(String username);
//query all users
Iterator<User> selectUserAll(Integer pageNum, Integer pageSize);
}
tab TestSpringDataJpaApplication.java
package com.oceanbase.testspringdatajpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestSpringDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringDataJpaApplication.class, args);
}
}
tab TestSpringDataJpaApplicationTests.java
package com.oceanbase.testspringdatajpa;
import com.oceanbase.testspringdatajpa.entity.User;
import com.oceanbase.testspringdatajpa.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Iterator;
@SpringBootTest
class TestSpringDataJpaApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
//insert
for (int i = 1; i <= 10; i++) {
userService.insertUser(new User(i, "insert" + i));
}
//delete
userService.deleteUser(1);
//update
userService.updateUser(new User(2, "update"));
//selectUserById
User user = userService.selectUserById(2);
System.out.println("user = " + user);
//selectUserByName
User userByName = userService.selectUserByName("insert");
System.out.println("userByName = " + userByName);
//query all users
Iterator<User> userIterator = userService.selectUserAll(0, 5);
userIterator.forEachRemaining(System.out::println);
}
}
:::
関連情報
OceanBase Connector/Jの詳細については、OceanBase JDBCドライバをご参照ください。