Spring Data JDBC for ScalarDB を使用した ScalarDB Cluster SQL をはじめよう
このページは英語版のページが機械翻訳されたものです。英語版との間に矛盾または不一致がある場合は、英語版を正としてください。
このチュートリアルでは、Spring Data JDBC for ScalarDB を介して ScalarDB Cluster SQL を使用してサンプルアプリケーションを作成する方法について説明します。
このサンプルアプリケーションの前提条件
- 以下のいずれかの Java Development Kit (JDK):
- Oracle JDK: 8、11、17、または 21 (LTS バージョン)
- OpenJDK ディストリビューション (Eclipse Temurin、Amazon Corretto、または Microsoft Build of OpenJDK): 8、11、17、または 21 (LTS バージョン)
- Kubernetes クラスターで実行されている ScalarDB Cluster
- ScalarDB Cluster をローカルにデプロイする方法 の手順に従ってデプロイした Kubernetes クラスターで ScalarDB Cluster が実行されていることを前提としています。
サンプルアプリケーション
このチュートリアルでは、Spring Data JDBC for ScalarDB を使用して、クレジットラインでアイテムを注文して支払うことができるサンプル電子商取引アプリケーションを作成するプロセスについて説明します。
次の図は、サンプルアプリケーションのシステムアーキテクチャを示しています。
+------------------------------------------------------------------------------------------------------------------------------+
| [Kubernetes クラスター] |
| |
| [ポッド] [ポッド] [ポッド] |
+------------------------+ | |
| SQL CLI | | +-------+ +------------------------+ |
| (間接クライアントモード) | --+ | +---> | Envoy | ---+ +---> | ScalarDB Cluster ノード | ---+ |
+------------------------+ | | | +-------+ | | +------------------------+ | |
| | | | | | |
| | +---------+ | +-------+ | +--------------------+ | +-----------------------+ | +------------+ |
+--+-> | サービス | ---+---> | Envoy | ---+---> | サービス | ---+---> | ScalarDB Cluster ノード | ---+---> | PostgreSQL | |
+------------------------+ | | | (Envoy) | | +-------+ | | (ScalarDB Cluster) | | +-----------------------+ | +------------+ |
| Spring Data JDBC for | | | +---------+ | | +--------------------+ | | |
| ScalarDB の | | | | +-------+ | | +------------------------+ | |
| サンプルアプリケーション | --+ | +---> | Envoy | ---+ +---> | ScalarDB Cluster ノード | ---+ |
| (間接クライアントモード) | | +-------+ +-----------------------+ |
+------------------------+ | |
+------------------------------------------------------------------------------------------------------------------------------+
ステップ 1. ScalarDB サンプルリポジトリをクローンする
git clone https://github.com/scalar-labs/scalardb-samples.git
cd scalardb-samples/spring-data-sample
ステップ 2. scalardb-sql.properties を変更する
ScalarDB Cluster に接続するには、scalardb-sql.properties も変更する必要があります。ただし、その前に、次のように Envoy (scalardb-cluster-envoy) のサービスリソースの EXTERNAL-IP アドレスを取得する必要があります。
kubectl get svc scalardb-cluster-envoy
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
scalardb-cluster-envoy LoadBalancer 10.105.121.51 localhost 60053:30641/TCP 16h
この場合、EXTERNAL-IP アドレスは localhost です。
次に、scalardb-sql.properties を開きます。
vim scalardb-sql.properties
次に、scalardb-sql.properties を次のように変更します。
scalar.db.sql.connection_mode=cluster
scalar.db.sql.cluster_mode.contact_points=indirect:localhost
ScalarDB Cluster に接続するには、scalar.db.sql.connection_mode プロパティに cluster を指定する必要があります。
また、このチュートリアルでは indirect クライアントモードを使用して Envoy のサービスリソースに接続します。
クライアントモードの詳細については、Java API を使用した ScalarDB Cluster の開発者ガイドを参照してください。
ステップ 3. スキ ーマをロードする
スキーマをロードするには、SQL CLI を使用する必要があります。SQL CLI は、使用している ScalarDB Cluster のバージョンに一致するものを ScalarDB リリースからダウンロードできます。JAR ファイルをダウンロードしたら、次のコマンドを実行して Cluster 用の SQL CLI を使用できます。<X.Y.Z> はそのバージョンに置き換えてください。
java -jar scalardb-cluster-sql-cli-<X.Y.Z>-all.jar --config scalardb-sql.properties --file schema.sql
ステップ 4.application.propertiesを変更する
次に、ScalarDB Cluster に接続するた めに application.properties も変更する必要があります。
vim src/main/resources/application.properties
scalardb-sql.properties と同様に、scalar.db.sql.connection_mode プロパティに cluster を指定し、indirect クライアントモードを使用する必要があります。そのためには、application.properties を次のように変更します。
spring.datasource.driver-class-name=com.scalar.db.sql.jdbc.SqlJdbcDriver
spring.datasource.url=jdbc:scalardb:\
?scalar.db.sql.connection_mode=cluster\
&scalar.db.sql.cluster_mode.contact_points=indirect:localhost\
&scalar.db.consensus_commit.isolation_level=SERIALIZABLE\
&scalar.db.sql.default_namespace_name=sample
ステップ 5. 初期データをロードする
サンプルアプリケーションを実行する前に、次のコマンドを実行して初期データをロードする必要があります。
./gradlew run --args="LoadInitialData"
初期データがロードされた後、次のレコードがテーブルに保存される必要があります。
sample.customersテーブルの場合:
| customer_id | name | credit_limit | credit_total |
|---|---|---|---|
| 1 | Yamada Taro | 10000 | 0 |
| 2 | Yamada Hanako | 10000 | 0 |
| 3 | Suzuki Ichiro | 10000 | 0 |
sample.itemsテーブルの場合:
| item_id | name | price |
|---|---|---|
| 1 | Apple | 1000 |
| 2 | Orange | 2000 |
| 3 | Grape | 2500 |
| 4 | Mango | 5000 |
| 5 | Melon | 3000 |
ステップ 6. サンプルアプリケーションを実行する
まず、ID が 1 である顧客に関する情報を取得します。
./gradlew run --args="GetCustomerInfo 1"
...
{"customer_id":1,"name":"Yamada Taro","credit_limit":10000,"credit_total":0}
...
次に、顧客 ID 1 を使用して、リンゴ3個とオレンジ2個を注文します。注文形式は <Item ID>:<Count>,<Item ID>:<Count>,... であることに注意してください。
./gradlew run --args="PlaceOrder 1 1:3,2:2"
...
{"order_id":"2358ab35-5819-4f8f-acb1-12e73d97d34e","customer_id":1,"timestamp":1677478005400}
...
このコマンドを実行すると、注文 ID が表示されます。
注文 ID を使用して注文の詳細を確認してみましょう。
./gradlew run --args="GetOrder 2358ab35-5819-4f8f-acb1-12e73d97d34e"
...
{"order_id":"2358ab35-5819-4f8f-acb1-12e73d97d34e","timestamp":1677478005400,"customer_id":1,"customer_name":"Yamada Taro","statements":[{"item_id":1,"item_name":"Apple","price":1000,"count":3,"total":3000},{"item_id":2,"item_name":"Orange","price":2000,"count":2,"total":4000}],"total":7000}
...
次に、別の注文を出して、顧客 ID 1 の注文履歴を取得しましょう。
./gradlew run --args="PlaceOrder 1 5:1"
...
{"order_id":"46062b16-b71b-46f9-a9ff-dc6b0991259b","customer_id":1,"timestamp":1677478201428}
...
./gradlew run --args="GetOrders 1"
...
[{"order_id":"46062b16-b71b-46f9-a9ff-dc6b0991259b","timestamp":1677478201428,"customer_id":1,"customer_name":"Yamada Taro","statements":[{"item_id":5,"item_name":"Melon","price":3000,"count":1,"total":3000}],"total":3000},{"order_id":"2358ab35-5819-4f8f-acb1-12e73d97d34e","timestamp":1677478005400,"customer_id":1,"customer_name":"Yamada Taro","statements":[{"item_id":1,"item_name":"Apple","price":1000,"count":3,"total":3000},{"item_id":2,"item_name":"Orange","price":2000,"count":2,"total":4000}],"total":7000}]
...
この注文履歴は、タイムスタンプの降順で表示されます。
顧客の現在の credit_total は 10000 です。顧客は、情報を取得したときに表示された credit_limit に達したため、これ以上注文することはできません。
./gradlew run --args="GetCustomerInfo 1"
...
{"id": 1, "name": "Yamada Taro", "credit_limit": 10000, "credit_total": 10000}
...
./gradlew run --args="PlaceOrder 1 3:1,4:1"
...
java.lang.RuntimeException: Credit limit exceeded. limit:10000, total:17500
at sample.SampleService.placeOrder(SampleService.java:102)
at sample.SampleService$$FastClassBySpringCGLIB$$1123c447.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at sample.SampleService$$EnhancerBySpringCGLIB$$a94e1d9.placeOrder(<generated>)
at sample.command.PlaceOrderCommand.call(PlaceOrderCommand.java:37)
at sample.command.PlaceOrderCommand.call(PlaceOrderCommand.java:13)
at picocli.CommandLine.executeUserObject(CommandLine.java:2041)
at picocli.CommandLine.access$1500(CommandLine.java:148)
at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2461)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2453)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2415)
at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2273)
at picocli.CommandLine$RunLast.execute(CommandLine.java:2417)
at picocli.CommandLine.execute(CommandLine.java:2170)
at sample.SampleApp.run(SampleApp.java:26)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:768)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
at sample.SampleApp.main(SampleApp.java:35)
...
支払いが完了すると、顧客は再度注文できるようになります。
./gradlew run --args="Repayment 1 8000"
...
./gradlew run --args="GetCustomerInfo 1"
...
{"customer_id":1,"name":"Yamada Taro","credit_limit":10000,"credit_total":2000}
...
./gradlew run --args="PlaceOrder 1 3:1,4:1"
...
{"order_id":"0350947a-9003-46f2-870e-6aa4b2df0f1f","customer_id":1,"timestamp":1677478728134}
...
サンプルアプリケーションのソースコード
Spring Data JDBC for ScalarDB の詳細については、サンプルアプリケーションのソースコードを確認してください。
参照
その他の ScalarDB Cluster チュートリアルについては、以下を参照してください。
- ScalarDB Cluster をはじめよう
- ScalarDB Cluster GraphQL をはじめよう
- JDBC 経由の ScalarDB Cluster SQL をはじめよう
- ScalarDB Cluster での Go をはじめよう
- ScalarDB Cluster での Python をはじめよう
Java API で ScalarDB Cluster を使用するアプリケーションの開発の詳細については、以下を参照してください。
ScalarDB Cluster gRPC API の詳細については、以下を参照してください。