Spring Bootフレームワークを利用したアプリケーションでMyBatisを利用する際、DBにアクセスするDataSource等のBean定義を自動的に行うことができるが、この機能を利用せず、手動でDBアクセス処理を定義しMyBatisを利用することもできる。
今回は、手動でDBアクセス処理を定義しMyBatisを利用してみたので、共有する。
前提条件
下記記事の実装が完了していること。
作成したサンプルプログラム(Azure Functions側)の内容
作成したサンプルプログラム(Azure Functions側)の構成は以下の通り。なお、App Services側のソースコードは修正していない。
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
<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を利用した実装サンプルは、以下の記事を参照のこと。
DB接続定義は、以下のXMLで定義している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="sqldb"> <!-- 接続先DB毎にenvironment要素を記載する --> <environment id="sqldb"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> <property name="url" value="jdbc:sqlserver://azure-db-purinit.database.windows.net:1433;database=azureSqlDatabase;columnEncryptionSetting=Enabled"/> <property name="username" value="purinit@azure-db-purinit"/> <property name="password" value="(DBのパスワード)"/> </dataSource> </environment> </environments> <!-- 参照するMapperのXMLファイル名を記載する --> <mappers> <mapper resource="com/example/mybatis/UserPassMapper.xml" /> </mappers> </configuration> |
また、application.propertiesのDB接続設定は不要になるため、削除している。
1 2 3 | # Key Vaultへの設定 keyVaultClientId=cdbb5434-e455-4885-b2e6-911f78c4264b keyVaultClientKey=(サービスプリンシパルのパスワード) |
さらに、DB接続定義(mybatis-config.xml)を読み込み、SqlSessionファクトリを生成し返却する処理を、以下のユーティリティクラスで定義している。
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 | package com.example.util; import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { /** SqlSessionファクトリ */ private static SqlSessionFactory sqlSessionFactory = null; static { try { // MyBatisの定義ファイルを読み込む Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); // SqlSessionファクトリを生成する // 第2引数には、MyBatisの定義ファイルの接続するDBを識別するidを指定する sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, "sqldb"); } catch (IOException e) { e.printStackTrace(); } } /** * SqlSessionファクトリを返却する * @return SqlSessionファクトリ */ public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } } |
また、Mapperインタフェースはクラスに変更し、@Repositoryアノテーションを付与し、各メソッド内でDBセッションの接続/切断する処理を追加している。
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 | package com.example.mybatis; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Repository; import com.example.mybatis.model.UserPass; import com.example.util.MyBatisUtil; @Repository public class UserPassMapper { /** * USER_PASSテーブルからデータを1件取得する. * @return USER_PASSテーブルからの取得結果 */ public UserPass selectOne() { SqlSession session = MyBatisUtil.getSqlSessionFactory().openSession(); UserPass userPass = (UserPass)session.selectOne("selectOne"); session.commit(); session.close(); return userPass; } /** * USER_PASSテーブルのデータを更新する. * @param userPass 更新対象のUSER_PASSテーブルの値 */ public void updateUserPass(UserPass userPass) { SqlSession session = MyBatisUtil.getSqlSessionFactory().openSession(); session.update("updateUserPass", userPass); session.commit(); session.close(); } } |
さらに、Azure Functionsのメインクラスは以下の通りで、@EnableAutoConfigurationアノテーションを付与し、Spring Bootのデータソース自動設定機能を無効にしている。
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 | package com.example; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.function.Function; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import com.example.model.GetUserPassParam; import com.example.model.GetUserPassResult; import com.example.model.UpdUserPassParam; import com.example.model.UpdUserPassResult; import com.example.service.GetUserPassService; import com.example.service.UpdUserPassService; import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionAzureKeyVaultProvider; import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionKeyStoreProvider; import com.microsoft.sqlserver.jdbc.SQLServerConnection; // DB接続を手動管理にするため、Spring Bootのデータソース自動設定機能を無効にする @SpringBootApplication @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) public class DemoAzureFunction { /** keyVaultのクライアントID */ @Value("${keyVaultClientId}") private String keyVaultClientId; /** keyVaultのクライアントキー */ @Value("${keyVaultClientKey}") private String keyVaultClientKey; /** Key Vaultの認証の接続設定が終わっているかどうかを判定するフラグ */ private static boolean keyVaultProviderFlg = false; /** USER_PASSデータ取得サービスクラスのオブジェクト */ @Autowired private GetUserPassService getUserPassService; /** USER_PASSデータ更新サービスクラスのオブジェクト */ @Autowired private UpdUserPassService updUserPassService; public static void main(String[] args) throws Exception { SpringApplication.run(DemoAzureFunction.class, args); } /** * Key Vaultの認証の接続設定を登録する. * @throws SQLException SQL例外 */ @PostConstruct public void postConstruct() throws SQLException { if (!keyVaultProviderFlg) { SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = new SQLServerColumnEncryptionAzureKeyVaultProvider( keyVaultClientId, keyVaultClientKey); Map<String, SQLServerColumnEncryptionKeyStoreProvider> keyStoreMap = new HashMap<String, SQLServerColumnEncryptionKeyStoreProvider>(); keyStoreMap.put(akvProvider.getName(), akvProvider); SQLServerConnection.registerColumnEncryptionKeyStoreProviders(keyStoreMap); keyVaultProviderFlg = true; } } /** * USER_PASSテーブルのデータを取得し結果を返却する関数 * @return USER_PASSテーブルデータ取得サービスクラスの呼出結果 */ @Bean public Function<GetUserPassParam, GetUserPassResult> getUserPass() { return getUserPassParam -> getUserPassService.getUserPass(getUserPassParam); } /** * USER_PASSテーブルのデータを更新し結果を返却する関数 * @return USER_PASSテーブルデータ更新サービスクラスの呼出結果 */ @Bean public Function<UpdUserPassParam, UpdUserPassResult> updUserPass(){ return updUserPassParam -> updUserPassService.updUserPass(updUserPassParam); } } |
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/always-encrypted-db-manual/demoAzureFunc
サンプルプログラムの実行結果
サンプルプログラムの実行結果は、以下の記事の「サンプルプログラムの実行結果」と同じになる。
要点まとめ
- Spring Bootフレームワークを利用したアプリケーションでMyBatisを利用する際、Spring Bootのデータソース自動設定機能を無効にして、手動でDBアクセス処理を定義しMyBatisを利用することもできる。