JULを利用して、MyBatisが発行したSQLの実行ログを記録する

# はじめに

「`java.util.logging`(以降は`JUL`と表記)を利用して、MyBatisが発行したSQLの実行ログを記録する」という、意外に珍しいことに取り組んだので、その際の手順を簡単に残しておきたいと思います。結構長い記事ですが、`logging.properties`の設定が最大の肝になるはずです。


# 注意

この記事は以下の環境で、稼働確認を行いましたが、バージョンやミドルウェアが異なる環境でも、動作すると思います。

- Postgres 10.5
- Java 11
- MyBatis 3.5.1
- Postgres JDBC 42.2.5


# 事前準備 (Postgres)

以下のような`users`テーブルを準備します。DBは`dev`、ユーザも`dev`になります。

```
dev=# \d users
              Table "public.users"
 Column | Type | Collation | Nullable | Default
--------+------+-----------+----------+---------
 id     | text |           | not null |
 name   | text |           | not null |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
```

# 事前準備 (Java プロジェクト)

以下の4つのモジュールを準備します。

1. `mybatis.logging.Main.java`: エントリポイント。メインメソッドが定義されている。
2. `mybatis.logging.repository.UsersRepository.java`: `users`テーブルへのMapperインターフェイス。
3. `mybatis-config.xml`: MyBatisで利用する、DBへの接続情報。
4. `logging.properties`: JULの設定。

```java:mybatis.logging.Main.java
package mybatis.logging;

import java.io.IOException;
import java.io.UncheckedIOException;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import mybatis.logging.repository.UsersRepository;

public class Main {
    public static void main(String[] args) {
        var builder = new SqlSessionFactoryBuilder();
        try (var in = Resources.getResourceAsStream("mybatis-config.xml")) {
            var factory = builder.build(in);
            try (var session = factory.openSession(true)) {
                var usersRepository = session.getMapper(UsersRepository.class);
                usersRepository.truncate();
                usersRepository.insert("1", "Alice");
                usersRepository.insert("2", "Bob");
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

```

```java:mybatis.logging.repository.UsersRepository.java
package mybatis.logging.repository;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

public interface UsersRepository {
    
    @Insert("INSERT INTO users (id, name) VALUES (#{id}, #{name})")
    int insert(@Param("id") String id, @Param("name") String name);
    
    @Delete("DELETE FROM users")
    int truncate();
}
```

```xml:mybatis-config.xml
<?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="dev">
    <environment id="dev">
      <transactionManager type="JDBC"></transactionManager>
      <dataSource type="POOLED">
        <property name="driver" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/dev"/>
        <property name="username" value="dev"/>
        <property name="password" value="password"/>
      </dataSource>
    </environment>
  </environments>
  
  <mappers>
    <mapper class="mybatis.logging.repository.UsersRepository" />
  </mappers>
</configuration>
```

```properties:logging.properties
# ROOT LOGGER
handlers = java.util.logging.ConsoleHandler
.level = INFO

# ConsoleHandler Default Setting
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# MyBatis LOGGER
mybatis.logging.repository.level = FINE
```

配置情報を画像で示したものが以下になります (Eclipse)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/e6c08251-cc82-dac3-8855-9dc2f876a175.png)


# 実行

あとはMainクラス=`mybatis.logging.Main`として、Javaを実行します。このときVMオプション`java.util.logging.config.file`にJUL用のpropertiesファイルを指定します(上記の例では`logging.properties`)。以下は`Eclipse`でVMオプションを設定する例になります。ここはお手元の環境に合わせて適宜変更してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/6c3ec41e-ca8f-d9e6-622e-21184b16b5d2.png)



# 結果

以下のようなログが標準出力に出力されれば成功です。ログをファイルなどに残したい場合は適宜handlerの指定を変更してください。

```
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==>  Preparing: DELETE FROM users 
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==> Parameters: 
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: <==    Updates: 2
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==>  Preparing: INSERT INTO users (id, name) VALUES (?, ?) 
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==> Parameters: 1(String), Alice(String)
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: <==    Updates: 1
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==>  Preparing: INSERT INTO users (id, name) VALUES (?, ?) 
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: ==> Parameters: 2(String), Bob(String)
4月 13, 2019 6:31:41 午後 org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl debug
普通: <==    Updates: 1
```

# 参考

- http://www.mybatis.org/mybatis-3/ja/logging.html
- http://www.mybatis.org/generator/reference/logging.html