Cosmos DBデータベースにアクセスする処理として、Azure Cosmos DB Spring Boot Starterという便利なライブラリがある。今回は、Azure App ServiceからCosmos DBデータベースにアクセスしてみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
また、下記記事のCosmos DBデータベースの作成が完了していること。
サンプルプログラムの作成
作成したサンプルプログラム(App Service側)の構成は以下の通り。なお、Azure Functions側のソースコードは修正していない。
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
pom.xmlの内容は以下の通りで、Azure Cosmos DBに接続するためのAzure Cosmos DB Spring Boot Starterを追加している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | <?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.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demoAzureApp</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>demoAzureApp</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-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- lombokの設定 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- Azure Cosmos DBに接続するための設定 --> <dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmosdb-spring-boot-starter</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </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> </plugin> <plugin> <groupId>com.microsoft.azure</groupId> <artifactId>azure-webapp-maven-plugin</artifactId> <version>1.12.0</version> <configuration> <schemaVersion>v2</schemaVersion> <subscriptionId>(ログインユーザーのサブスクリプションID)</subscriptionId> <resourceGroup>azureAppDemo</resourceGroup> <appName>azureAppDemoService</appName> <pricingTier>B1</pricingTier> <region>japaneast</region> <appServicePlanName>ASP-azureAppDemo-8679</appServicePlanName> <appServicePlanResourceGroup>azureAppDemo</appServicePlanResourceGroup> <runtime> <os>Linux</os> <javaVersion>Java 8</javaVersion> <webContainer>Tomcat 8.5</webContainer> </runtime> <deployment> <resources> <resource> <directory>${project.basedir}/target</directory> <includes> <include>*.war</include> </includes> </resource> </resources> </deployment> </configuration> </plugin> </plugins> </build> </project> |
application.propertiesの内容は以下の通りで、Azure Cosmos DBの接続先を設定している。
1 2 3 4 5 6 7 | server.port = 8084 # Azure Cosmos DB接続先 # ここでは、URI、プライマリキー、データベースを指定している azure.cosmosdb.uri=https://azurecosmospurinit.documents.azure.com:443/ azure.cosmosdb.key=(プライマリキー) azure.cosmosdb.database=purinitdb |
なお、上記のURIとキーは、以下の画面のURIとプライマリキーから取得している。
また、上記のデータベース名と後述のコンテナ名は、以下のデータ エクスプローラー画面から取得している。
また、UserDataクラスの内容は以下の通りで、コレクションにコンテナ名を指定している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package com.example.demo; import org.springframework.data.annotation.Id; import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; import lombok.Data; //Cosmos DBのユーザーデータテーブルのエンティティ //collectionにCosmos DBのコンテナ名を指定する @Data @Document(collection = "purinitcontainer") public class UserData { /** ID */ @Id private String id; /** 名前 */ private String name; /** 生年月日_年 */ private Integer birth_year; /** 生年月日_月 */ private Integer birth_month; /** 生年月日_日 */ private Integer birth_day; /** 性別 */ private String sex; } |
さらに、Cosmos DBのユーザーデータテーブルを操作するリポジトリの内容は以下の通りで、Cosmos DBにアクセスするためのReactiveCosmosRepositoryインタフェースを継承し、検索に必要なメソッドをいくつか追加している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.example.demo; import org.springframework.stereotype.Repository; import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository; import reactor.core.publisher.Flux; // Cosmos DBのユーザーデータテーブルを操作するためのリポジトリ @Repository public interface UserDataRepository extends ReactiveCosmosRepository<UserData, String> { /** * ユーザーデータテーブルから、指定した性別に完全一致するデータを返す * @param sex 性別 * @return 検索結果 */ public Flux<UserData> findBySex(String sex); /** * ユーザーデータテーブルから、指定した名前に部分一致するデータを返す * @param name 名前 * @return 検索結果 */ public Flux<UserData> findByNameContains(String name); /** * ユーザーデータテーブルから、指定した名前に部分一致し、性別に完全一致するデータを返す * @param name 名前 * @param sex 性別 * @return 検索結果 */ public Flux<UserData> findByNameContainsAndSex(String name, String sex); } |
また、コントローラクラスの内容は以下の通りで、searchメソッド内で前述のリポジトリを呼び出している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | package com.example.demo; import java.util.ArrayList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import reactor.core.publisher.Flux; @Controller public class DemoController { /** DBからユーザーデータを取得するリポジトリ */ @Autowired private UserDataRepository userDataRepository; /** * 検索一覧画面を初期表示する * @param model Modelオブジェクト * @return 検索一覧画面 */ @GetMapping("/") public String index(Model model) { SearchForm searchForm = new SearchForm(); model.addAttribute("searchForm", searchForm); return "list"; } /** * 検索条件に合うユーザーデータを取得し、一覧に表示する * @param searchForm 検索条件Form * @param model Modelオブジェクト * @return 検索一覧画面 */ @PostMapping("/search") public String search(SearchForm searchForm, Model model) { // 検索条件に合うユーザーデータを取得する ArrayList<UserData> userDataList = search(searchForm); searchForm.setUserDataList(userDataList); model.addAttribute("searchForm", searchForm); return "list"; } /** * DBから検索条件に合うユーザーデータを取得する * @param searchForm 検索条件Form * @return 検索結果 */ private ArrayList<UserData> search(SearchForm searchForm) { Flux<UserData> userDataFlux = null; // 検索条件に名前、性別が両方指定されている場合 if (!StringUtils.isEmpty(searchForm.getSearchName()) && !StringUtils.isEmpty(searchForm.getSearchSex())) { userDataFlux = userDataRepository.findByNameContainsAndSex( searchForm.getSearchName(), searchForm.getSearchSex()); // 検索条件に名前が指定されている場合 } else if (!StringUtils.isEmpty(searchForm.getSearchName())) { userDataFlux = userDataRepository.findByNameContains( searchForm.getSearchName()); // 検索条件に性別が指定されている場合 } else if (!StringUtils.isEmpty(searchForm.getSearchSex())) { userDataFlux = userDataRepository.findBySex(searchForm.getSearchSex()); // 検索条件未指定の場合 } else { userDataFlux = userDataRepository.findAll(); } // 性別(1,2)を(男,女)に変換し返す ArrayList<UserData> userDataList = new ArrayList<>(); for (UserData userData : userDataFlux.collectList().block()) { userData.setSex("1".equals(userData.getSex()) ? "男" : "女"); userDataList.add(userData); } return userDataList; } } |
さらに、HTMLファイルの内容は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>検索一覧画面</title> </head> <body> <form method="post" th:action="@{/search}" th:object="${searchForm}"> <table border="1" cellpadding="5"> <tr> <th>名前</th> <td><input type="text" th:value="*{searchName}" th:field="*{searchName}" /></td> </tr> <tr> <th>性別</th> <td> <select th:field="*{searchSex}"> <option value=""></option> <option th:each="item : *{getSexItems()}" th:value="${item.key}" th:text="${item.value}"/> </select> </td> </tr> </table> <br/><br/> <input type="submit" value="検索" /> <br/><br/><br/><br/> <table border="1" cellpadding="5"> <tr> <th width="40">ID</th> <th width="180">名前</th> <th width="180">生年月日</th> <th width="40">性別</th> </tr> <tr th:each="obj : *{userDataList}"> <td th:text="${obj.id}" align="center"></td> <td th:text="${obj.name}" align="center"></td> <td th:text="|${obj.birth_year}年 ${obj.birth_month}月 ${obj.birth_day}日|" align="center"></td> <td th:text="${obj.sex}" align="center"></td> </tr> </table> </form> </body> </html> |
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-app-service-to-cosmos-db/demoAzureApp
サンプルプログラムの実行結果
サンプルプログラムの実行結果は、以下の通り。
1)「mvn azure-webapp:deploy」コマンドによって、Azure App Service上にサンプルプログラムをデプロイする。
なお、Azure App Serviceにデプロイする過程は、以下の記事の「App ServiceへのSpring Bootを利用したJavaアプリケーションのデプロイ」を参照のこと。
2) Azure App ServiceのURL「https://azureappdemoservice.azurewebsites.net/」とアクセスした場合の実行結果は、以下の通り。
なお、上記URLは、下記Azure App ServiceのURLから確認できる。
3) 名前、性別を指定せず「検索」ボタンを押下すると、以下のように、登録データが全て表示される。
4) 性別を指定し「検索」ボタンを押下すると、以下のように、指定した性別のデータが表示される。
5) 名前、性別を指定し「検索」ボタンを押下すると、以下のように、指定した名前、性別のデータが表示される。
要点まとめ
- Cosmos DBデータベースにアクセスする処理は、Azure Cosmos DB Spring Boot Starterというライブラリを利用すると便利である。