Gradle で Multi-project を作成する ( その11 )( doma2lib+cmdapp+webapp編、log4jdbc-log4j2 を導入してトランザクションが有効なことを確認する )
概要
記事一覧はこちらです。
Gradle で Multi-project を作成する ( その10 )( doma2lib+cmdapp+webapp編、sample-cmdapp プロジェクトを作成する2 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
目次
- gradle-multiprj-doma2lib-cmdwebapp の build.gradle を変更する
- doma2-lib の src/main/resources の下に application-develop.properties、application-product.properties を作成する
- doma2-lib の db-product.properties と同じ内容を db-develop.properties に記述する
- EmployeeDataCsvToDbLoaderTest クラスでトランザクションが有効か確認する
java.sql.SQLSyntaxErrorException: SELECT command denied to user 'sampledb_user'@'172.18.0.1' for table 'user_variables_by_thread'
を解消する- sample-cmdapp をコマンドラインから実行した時にトランザクションが有効か確認する
手順
gradle-multiprj-doma2lib-cmdwebapp の build.gradle を変更する
gradle-multiprj-doma2lib-cmdwebapp の build.gradle の configure に log4jdbc-log4j2 を利用するための com.integralblue:log4jdbc-spring-boot-starter を依存関係に追加します。
.......... configure(subprojects.findAll { it.name ==~ /^(doma2-lib|sample-cmdapp)$/ }) { apply plugin: "org.springframework.boot" dependencyManagement { imports { mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) } } ext { jdbcDriver = "mysql:mysql-connector-java:8.0.15" domaVersion = "2.24.0" } dependencies { def lombokVersion = "1.18.6" testImplementation("org.springframework.boot:spring-boot-starter-test") runtimeOnly(jdbcDriver) implementation("org.seasar.doma.boot:doma-spring-boot-starter:1.1.1") implementation("org.seasar.doma:doma:${domaVersion}") implementation("org.flywaydb:flyway-core:5.2.4") implementation("com.integralblue:log4jdbc-spring-boot-starter:1.0.2") // for lombok // testAnnotationProcessor、testCompileOnly を併記しなくてよいよう configurations で設定している annotationProcessor("org.projectlombok:lombok:${lombokVersion}") compileOnly("org.projectlombok:lombok:${lombokVersion}") } }
implementation("com.integralblue:log4jdbc-spring-boot-starter:1.0.2")
を追加します。
doma2-lib の src/main/resources の下に application-develop.properties、application-product.properties を作成する
develop profile の時には log4jdbc-log4j2 でログが出力されるようにし、product profile の時にはログが出力されないようにします。設定ファイルは doma2-lib プロジェクトの下に作成します(ここに作成しても sample-cmdapp に適用されます)。
doma2-lib/src/main/resources の下に application-develop.properties、application-product.properties を新規作成し、以下の内容を記述します。
■application-develop.properties
# log4jdbc-log4j2 logging.level.jdbc.sqlonly=DEBUG logging.level.jdbc.sqltiming=INFO logging.level.jdbc.audit=INFO logging.level.jdbc.resultset=ERROR logging.level.jdbc.resultsettable=ERROR logging.level.jdbc.connection=DEBUG
■application-product.properties
spring.autoconfigure.exclude=com.integralblue.log4jdbc.spring.Log4jdbcAutoConfiguration
doma2-lib の db-product.properties と同じ内容を db-develop.properties に記述する
develop profile ではログが出力され product profile ではログが出力されないことを確認できるようにするために doma2-lib/src/main/resources/db-product.properties の内容を db-develop.properties と同じにします。
■db-product.properties
doma.dialect=mysql spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost/sampledb?sslMode=DISABLED&characterEncoding=utf8 spring.datasource.hikari.username=sampledb_user spring.datasource.hikari.password=xxxxxxxx spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.hikari.leak-detection-threshold=60000 spring.datasource.hikari.register-mbeans=true
EmployeeDataCsvToDbLoaderTest クラスでトランザクションが有効か確認する
sample-cmdapp/src/test/java/ksbysample/app/samplecmdapp/EmployeeDataCsvToDbLoaderTest.groovy のテストを実行して、employeeDataCsvToDbLoader = (EmployeeDataCsvToDbLoader) context.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(employeeDataCsvToDbLoader, "employeeDataCsvToDbLoader")
で手動で Bean に登録した場合にトランザクションが有効か確認します。
テストを実行すると insert 前に Connection.setAutoCommit(false)
が呼び出されて、employeeDataCsvToDbLoader.run(...)
で2件 insert した後に Connection.commit()
が呼び出されていることが確認できました。
わざと RuntimeException を throw して rollback されるかも確認します。 sample-cmdapp/src/main/java/ksbysample/app/samplecmdapp/EmployeeDataCsvToDbLoader.java を以下のように変更します。
@Component @ConditionalOnProperty(value = {"batch.execute"}, havingValue = "EmployeeDataCsvToDbLoader") public class EmployeeDataCsvToDbLoader implements CommandLineRunner { .......... @Override @Transactional public void run(String... args) throws Exception { .......... // CSV ファイルを1行ずつ読み込み employee テーブルに insert する try (BufferedReader br = Files.newBufferedReader(Paths.get(this.csvfile), StandardCharsets.UTF_8)) { Employee employee = new Employee(); for (EmployeeCsvRecord employeeCsvRecord : routines.iterate(EmployeeCsvRecord.class, br)) { modelMapper.map(employeeCsvRecord, employee); employeeDao.insert(employee); throw new RuntimeException("error"); } } } }
throw new RuntimeException("error");
を追加します。
テストを実行すると1件目の insert 文が実行された後に RuntimeException が throw された結果 Connection.rollback()
が呼び出されていました。
トランザクションが有効になっていることが確認できました。
また spring.profiles.active=product
に変更すると、
@SpringBootTest(properties = ["spring.profiles.active=product"]) class EmployeeDataCsvToDbLoaderTest extends Specification {
log4jdbc-log4j2 のログは出力されなくなりました。
java.sql.SQLSyntaxErrorException: SELECT command denied to user 'sampledb_user'@'172.18.0.1' for table 'user_variables_by_thread'
を解消する
上でテストを実行した時に java.sql.SQLSyntaxErrorException: SELECT command denied to user 'sampledb_user'@'172.18.0.1' for table 'user_variables_by_thread'
というエラーメッセージが出ていることに気づきました。flyway が performance_schema.user_variables_by_thread テーブルにアクセスしようとして出来なかったために出力されていました。
doma2-lib/src/main/resources/db/init/create_database.sql を以下のように変更します。
create database if not exists sampledb character set utf8mb4 collate utf8mb4_ja_0900_as_cs_ks; create user 'sampledb_user'@'%' identified by 'xxxxxxxx'; grant all privileges ON sampledb.* to 'sampledb_user'@'%' with grant option; grant select ON performance_schema.user_variables_by_thread to 'sampledb_user'@'%'; flush privileges;
grant select ON performance_schema.user_variables_by_thread to 'sampledb_user'@'%';
を追加します。
コンテナを再起動しても create_database.sql に追加した grant select ON ...
文が実行されなかったので、adminer に root ユーザでログインして直接 SQL 文を実行します。
テストを実行すると今度はエラーメッセージが出力されなくなりました。
sample-cmdapp をコマンドラインから実行した時にトランザクションが有効か確認する
コマンドラインから実行した時もトランザクションが有効になっているか確認します。まずは clean タスク実行 → Rebuild Project 実行 → build タスク実行を行い、sample-cmdapp-1.0.0-RELEASE.jar を build し直します。
java -Dspring.profiles.active=develop -Dbatch.execute=EmployeeDataCsvToDbLoader -jar sample-cmdapp-1.0.0-RELEASE.jar -csvfile=D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\src\test\resources\employee.csv
コマンドを実行すると Connection.commit()
が呼び出されています。
(.....途中省略.....)
sample-cmdapp/src/main/java/ksbysample/app/samplecmdapp/EmployeeDataCsvToDbLoader.java に throw new RuntimeException("error");
を追加してから build し直した後、再度コマンドを実行すると1件目を insert した後 Connection.rollback()
が呼び出されていました。
コマンドラインから実行した時もトランザクションが有効になっていることが確認できました。
また -Dspring.profiles.active=product
に変更した java -Dspring.profiles.active=product -Dbatch.execute=EmployeeDataCsvToDbLoader -jar sample-cmdapp-1.0.0-RELEASE.jar -csvfile=D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\src\test\resources\employee.csv
コマンドを実行すると log4jdbc-log4j2 のログは出力されませんでした。
履歴
2019/05/01
初版発行。