データベースへアクセスする処理は、通常のSpring Boot上でのアプリケーション開発の場合と同様に、MyBatis等のDBアクセスフレームワークを利用すればよい。
今回は、MyBatisを利用して、Azure FunctionsからSQL Databaseにアクセスしてみたので、そのサンプルプログラムを共有する。
前提条件
下記記事に従ってAzure Functionsのサンプルプログラムを作成済であること。
また、下記記事に従ってSQL DatabaseにUSER_DATAテーブルを作成済であること。
さらに、下記記事に従ってSTSにLombokをインストール済であること。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、前提条件のAzure Functionsのサンプルプログラムから変更したプログラムである。
<2021年4月13日 追記>
spring-cloud-function-dependenciesのバージョンは、2021年3月16日にリリースしたバージョン3.1.2を利用すると、1つのAzure Functions内に複数のファンクションを含む場合の不具合が解消できている。
その場合、Handlerクラスの継承するクラスを「AzureSpringBootRequestHandler」クラスから「FunctionInvoker」クラスに変更する。
spring-cloud-function-dependenciesの3.1.2を利用した実装サンプルは、以下の記事を参照のこと。
pom.xmlに追加した内容は以下の通りで、SQL Server、MyBatis、Lombokの定義を追加している。なお、SQL Serverは、SQL Databaseにアクセスするために利用している。
<!-- SQL Serverを利用するための設定 --> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <!-- mybatisを利用するための設定 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <!-- lombokを利用するための設定 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency>
application.propertiesに追加した内容は以下の通りで、SQL Databaseにアクセスするためのアクセス情報を定義している。
# DB接続設定 spring.datasource.url=jdbc:sqlserver://azure-db-purinit.database.windows.net:1433;database=azureSqlDatabase spring.datasource.username=purinit@azure-db-purinit spring.datasource.password=(パスワード) spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
なお、SQL Databaseへ接続するJDBC接続文字列は、以下のように確認できる。
また、USER_DATAテーブルからデータを取得する処理は、以下のプログラムで実装している。
package com.example.mybatis.model; import lombok.Data; @Data public class UserData { /** ID */ private int id; /** 名前 */ private String name; /** 生年月日_年 */ private int birth_year; /** 生年月日_月 */ private int birth_month; /** 生年月日_日 */ private int birth_day; /** 性別 */ private String sex; /** メモ */ private String memo; }
package com.example.mybatis; import org.apache.ibatis.annotations.Mapper; import com.example.mybatis.model.UserData; @Mapper public interface UserDataMapper { /** * 引数のIDに対応するユーザーデータをDBから取得する * @param id ID * @return DBのユーザーデータ */ UserData getUserData(int id); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mybatis.UserDataMapper"> <resultMap id="userDataResultMap" type="com.example.mybatis.model.UserData" > <result column="id" property="id" jdbcType="INTEGER" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="birth_year" property="birth_year" jdbcType="INTEGER" /> <result column="birth_month" property="birth_month" jdbcType="INTEGER" /> <result column="birth_day" property="birth_day" jdbcType="INTEGER" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="memo" property="memo" jdbcType="VARCHAR" /> </resultMap> <select id="getUserData" parameterType="java.lang.Integer" resultMap="userDataResultMap"> SELECT id, name, birth_year, birth_month, birth_day, sex, memo FROM USER_DATA WHERE id = #{id} </select> </mapper>
また、USER_DATAテーブルからデータを取得するMapperクラスを呼び出すサービスクラスの内容は、以下の通り。
package com.example.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.example.model.Greeting; import com.example.model.User; import com.example.mybatis.UserDataMapper; import com.example.mybatis.model.UserData; @Service public class HelloService { /** DBからユーザーデータを取得するMapperオブジェクト */ @Autowired private UserDataMapper mapper; /** * DBからユーザーデータを取得しGreetingオブジェクトを返却する * @param user HttpRequestの引数のユーザー * @return Greetingオブジェクト */ public Greeting sayHello(User user) { UserData userData = mapper.getUserData(1); return new Greeting("Welcome, " + user.getName() + ", DBからの取得結果 : " + userData.toString()); } }
さらに、上記サービスクラスは、以下のファンクションクラスから呼び出している。
package com.example; import com.example.model.Greeting; import com.example.model.User; import com.example.service.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import java.util.function.Function; @SpringBootApplication public class HelloFunction { /** サービスクラスのオブジェクト */ @Autowired private HelloService helloService; public static void main(String[] args) throws Exception { SpringApplication.run(HelloFunction.class, args); } /** * Userオブジェクトを引数に、サービスクラスの呼出結果を返却する関数 * @return サービスクラスの呼出結果 */ @Bean public Function<User, Greeting> hello() { return user -> helloService.sayHello(user); } }
また、上記ファンクションクラスの引数・戻り値である以下のクラスは、Lombokを利用するようにしている。
package com.example.model; import lombok.Data; @Data public class User { public User() { } public User(String name) { this.name = name; } /** 名前 */ private String name; }
package com.example.model; import lombok.Data; @Data public class Greeting { public Greeting() { } public Greeting(String message) { this.message = message; } /** メッセージ */ private String message; }
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-functions-to-sql-database/demoAzureFunc
サンプルプログラムの実行結果
サンプルプログラムの実行結果は、以下の通り。
1) ローカル環境でdemoAzureFuncアプリを「mvn azure-functions:run」コマンドで起動する。
2) その後、「http://localhost:7071/api/hello?name=Azure」とアクセスした場合の実行結果は以下の通りで、メッセージにUSER_DATAテーブルの取得結果が表示される。
3) Azure Functionsにデプロイ後、「https://azurefuncdemoapp.azurewebsites.net/api/hello?name=Azure」とアクセスした場合の実行結果は以下の通りで、メッセージにUSER_DATAテーブルの取得結果が表示される。
なお、Azure Functionsにデプロイする過程は、以下の記事の「Azure FunctionsへのSpring Bootを利用したJavaアプリケーションのデプロイ」を参照のこと。
要点まとめ
- データベースへアクセスする処理は、通常のSpring Boot上でのアプリケーション開発の場合と同様に、MyBatis等のDBアクセスフレームワークを利用すればよい。
- SQL Databaseへ接続するJDBC接続文字列を確認するには、Azure Portalの概要ページの「データベース接続文字列の表示」リンクを押下後、「JDBC」タブを押下する。