Azure DB連携

Azure FunctionsからSQL Databaseにアクセスしてみた

データベースへアクセスする処理は、通常のSpring Boot上でのアプリケーション開発の場合と同様に、MyBatis等のDBアクセスフレームワークを利用すればよい。

今回は、MyBatisを利用して、Azure FunctionsからSQL Databaseにアクセスしてみたので、そのサンプルプログラムを共有する。

前提条件

下記記事に従ってAzure Functionsのサンプルプログラムを作成済であること。

Azure Functions上でSpring Bootを利用したJavaアプリケーションを作成してみた前回は、Azure Potal上でAzure Functionsを作成してみたが、今回は、前回作成したAzure FunctionsにS...

また、下記記事に従ってSQL DatabaseにUSER_DATAテーブルを作成済であること。

Azure Potal上でSQLデータベースを作成してみたAzure Portal上では、常に最新の安定したバージョンの SQL Serverデータベースである「SQL データベース」が利用でき...

さらに、下記記事に従ってSTSにLombokをインストール済であること。

STS(Spring Tool Suite)上でlombokを利用してみた今回は、STSを利用して、lombokを利用してみたので、その手順を共有する。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を利用した実装サンプルは、以下の記事を参照のこと。

spring-cloud-function-dependenciesのバージョンを最新(3.1.2)にしてみたこれまでこのブログで取り上げてきたAzure Functionsのサンプルプログラムでは、spring-cloud-function-d...

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接続文字列は、以下のように確認できる。
SQLデータベース_JDBC_1

SQLデータベース_JDBC_2



また、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>

上記ソースコードによって、以下のSQL文が実行される。
user_dataテーブルのデータ



また、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」コマンドで起動する。
サンプルプログラムの実行結果_1

2) その後、「http://localhost:7071/api/hello?name=Azure」とアクセスした場合の実行結果は以下の通りで、メッセージにUSER_DATAテーブルの取得結果が表示される。
サンプルプログラムの実行結果_2

3) Azure Functionsにデプロイ後、「https://azurefuncdemoapp.azurewebsites.net/api/hello?name=Azure」とアクセスした場合の実行結果は以下の通りで、メッセージにUSER_DATAテーブルの取得結果が表示される。
サンプルプログラムの実行結果_3

なお、Azure Functionsにデプロイする過程は、以下の記事の「Azure FunctionsへのSpring Bootを利用したJavaアプリケーションのデプロイ」を参照のこと。

Azure Functions上でSpring Bootを利用したJavaアプリケーションを作成してみた前回は、Azure Potal上でAzure Functionsを作成してみたが、今回は、前回作成したAzure FunctionsにS...

要点まとめ

  • データベースへアクセスする処理は、通常のSpring Boot上でのアプリケーション開発の場合と同様に、MyBatis等のDBアクセスフレームワークを利用すればよい。
  • SQL Databaseへ接続するJDBC接続文字列を確認するには、Azure Portalの概要ページの「データベース接続文字列の表示」リンクを押下後、「JDBC」タブを押下する。