コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

MirageのインストールとSLF4Jの設定

2WaySQLが使えるシンプルなデータベースアクセスライブラリーのMirageを使ってみました。

ソース自体は、ドキュメントにあるものに少し手を加えたものですが、ログ出力をSFL4Jにしたかったのでその点を調べてみました。

Mirageのインストール

ドキュメントの通り、pom.xmlを以下のようにします。今回はデータベースにH2を使うのでH2のJDBCドライバも一緒に入れておきます。

<repositories>
 <repository>
  <id>amateras</id>
  <name>Project Amateras Maven2 Repository</name>
  <url>http://amateras.sourceforge.jp/mvn/</url>
 </repository>
</repositories>

<dependencies>
 <dependency>
  <groupId>jp.sf.amateras.mirage</groupId>
  <artifactId>mirage</artifactId>
  <version>1.1.6</version>
 </dependency>
 <dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <version>1.3.171</version>
  <scope>runtime</scope>
 </dependency>
</dependencies>

H2の起動と準備

別途H2データベースを起動しておきます。導入はzipファイルをダウンロードします。

展開したディレクトリのbin/h2.shに実行権限を与え実行するとH2データベースが起動します。

$ chmod 744 h2.sh
$ ./h2.sh

起動するとブラウザが立ち上がるのでそのまま接続します。JDBC URLやUser Name、PasswordはMirageから接続する際にも使用するのでメモしておきます。

Mirageのサイトにあるサンプルに近い形で動かしたいので以下のDDLでテーブルを作成します。

CREATE TABLE book(
  book_id INT,
  book_name VARCHAR(80),
  author VARCHAR(40),
  price INT,
  PRIMARY KEY(book_id)
)

適当にデータをinsertします。

INSERT INTO book VALUES(1,'よくわかるMirage','テスト太郎',1980);
INSERT INTO book VALUES(2,'基礎からのH2','H2花子',2000);

テーブルデータの読み込み

Mirageのサイトとほぼ同じものを作成します。
bookテーブルに対応したPOJOクラスのBookを作成します。

package com.example.mirage.mirageSample;

import jp.sf.amateras.mirage.annotation.PrimaryKey;
import jp.sf.amateras.mirage.annotation.PrimaryKey.GenerationType;

public class Book {
    @PrimaryKey(generationType = GenerationType.APPLICATION)
    public Integer bookId;
    public String bookName;
    public String author;
    public Integer price;

    @Override
    public String toString() {
        return "Book [bookId=" + bookId + ", bookName=" + bookName
                + ", author=" + author + ", price=" + price + "]";
    }
}

データの取得もMirageのサンプル通りです。

package com.example.mirage.mirageSample;

import java.util.List;

import jp.sf.amateras.mirage.SqlManager;
import jp.sf.amateras.mirage.session.Session;
import jp.sf.amateras.mirage.session.SessionFactory;

public class BookMain {

    public static void main(String[] args) {
        Session session = SessionFactory.getSession();
        SqlManager sqlManager = session.getSqlManager();
        session.begin();

        try {
            BookParam param = new BookParam();

            List<Book> result = sqlManager.getResultList(Book.class,
                    "META-INF/selectBook.sql", param);

            for (Book book : result) {
                System.out.println(book);
            }

            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        } finally {
            session.release();
        }
    }

}

実行するとコンソールに以下のように表示されます。

4 19, 2013 7:57:19 午後 jp.sf.amateras.mirage.session.JDBCSessionImpl begin
情報: Begin transaction.
4 19, 2013 7:57:19 午後 jp.sf.amateras.mirage.SqlExecutor printSql
情報: SELECT * FROM BOOK
ORDER BY BOOK_ID ASC
4 19, 2013 7:57:19 午後 jp.sf.amateras.mirage.session.JDBCSessionImpl commit
情報: Commit transaction.
4 19, 2013 7:57:19 午後 jp.sf.amateras.mirage.provider.DefaultConnectionProvider releaseConnection
情報: Connection is released.
Book [bookId=1, bookName=よくわかるMirage, author=テスト太郎, price=1980]
Book [bookId=2, bookName=基礎からのH2, author=H2花子, price=2000]

最後の2行が今回のプログラムで記述した出力で、それ以外はMirageの内部的に出力しているログになります。今回の目的はこのログをSLF4J経由でLogbackに出力することになります。

SLF4J+Logbackでログを出力する

SLF4JとLogbackを使用するには、pom.xmlに以下の記述をします。

<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
 <version>1.0.11</version>
</dependency>

実際には、logback-classicの他に、logback-core、slf4j-apiも必要ですが、logback-classicを入れると一緒に入ります。

次に、ログ出力の設定を記述します。ファイルはクラスパスのルートにlogback.xmlというファイルを置きます。この辺りはいろいろルールがあるのでドキュメントを参照してください。以下の設定は、コンソールにinfo以上のレベルのログを出力します。

<configuration>
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
   <pattern>%d{yyyy.MM.dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
  </encoder>
 </appender>

 <root level="info">
  <appender-ref ref="STDOUT" />
 </root>
</configuration>

最後に、ログ出力のコードを追加します。
最初にロガーを取得します。

private static final Logger logger = LoggerFactory.getLogger(BookMain.class);

System.outしていた部分をloggerで置き換えます。

logger.info(book.toString());

実行するとコンソールの出力が以下のように変わります。

4 19, 2013 9:36:16 午後 jp.sf.amateras.mirage.session.JDBCSessionImpl begin
情報: Begin transaction.
4 19, 2013 9:36:17 午後 jp.sf.amateras.mirage.SqlExecutor printSql
情報: SELECT * FROM BOOK
ORDER BY BOOK_ID ASC
2013.04.19 21:36:17.054 [main] INFO  c.e.mirage.mirageSample.BookMain - Book [bookId=1, bookName=よくわかるMirage, author=テスト太郎, price=1980]
2013.04.19 21:36:17.058 [main] INFO  c.e.mirage.mirageSample.BookMain - Book [bookId=2, bookName=基礎からのH2, author=H2花子, price=2000]
4 19, 2013 9:36:17 午後 jp.sf.amateras.mirage.session.JDBCSessionImpl commit
情報: Commit transaction.
4 19, 2013 9:36:17 午後 jp.sf.amateras.mirage.provider.DefaultConnectionProvider releaseConnection
情報: Connection is released.

2013.04.19という文字列から始まっている行が今回Logbackで出力したログになります。Mirageのログは最初に行ったときと同じままということがわかります。

次に、このMirageのログもLogbackから出力するように設定をしてみます。

JDKのログをSLF4J経由でLogbackへ出力する

MirageのログはJDK標準のLoggerから出力されています。JDK標準のログ出力については、Java Logging APIを参照ください。

JDKのログをSLF4Jに移譲するためにはブリッジを使います。Mavenに以下の設定を追加して、JDKのログ→SLF4Jのブリッジを準備します。

<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>jul-to-slf4j</artifactId>
 <version>1.7.4</version>
</dependency>

これだけだとまだ、ログの移譲はできていません。以下の2つのうちのいずれかの設定をする必要があります。

この辺りは、SLF4Jのドキュメントにも詳しく記載されています。

まず1点目ですが、プログラムからブリッジの設定をします。mainメソッドの先頭に以下の行を追加します。

SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5)
SLF4JBridgeHandler.install();

2つ目は設定ファイルの記述でブリッジの設定ができます。設定ファイルは起動時のVMオプションにその場所を指定します。設定しない場合には、デフォルトのファイルが使用されます。

-Djava.util.logging.config.file=src/main/resources/logging.properties

デフォルトの設定ファイルは、以下の場所になります。

$JAVA_HOME/jre/lib/logging.properties

デフォルトの設定ファイルを変更すると同じJDKを使用するすべてのシステムに影響をおよぼすので、注意が必要です。

ファイル自体は以下の内容です。

handlers = org.slf4j.bridge.SLF4JBridgeHandler

プログラムで設定しても、ファイルで設定しても結果は同じで、以下のようにすべてのログがSLF4Jを通して、Logbackに出力されます。

2013.04.19 22:30:57.209 [main] INFO  j.s.a.mirage.session.JDBCSessionImpl - Begin transaction.
2013.04.19 22:30:57.418 [main] INFO  jp.sf.amateras.mirage.SqlExecutor - SELECT * FROM BOOK
ORDER BY BOOK_ID ASC
2013.04.19 22:30:57.446 [main] INFO  c.e.mirage.mirageSample.BookMain - Book [bookId=1, bookName=よくわかるMirage, author=テスト太郎, price=1980]
2013.04.19 22:30:57.446 [main] INFO  c.e.mirage.mirageSample.BookMain - Book [bookId=2, bookName=基礎からのH2, author=H2花子, price=2000]
2013.04.19 22:30:57.446 [main] INFO  j.s.a.mirage.session.JDBCSessionImpl - Commit transaction.
2013.04.19 22:30:57.447 [main] INFO  j.s.a.m.p.DefaultConnectionProvider - Connection is released.