Spring bootにおいてSuper classでJdbcTemplateをautowaredしても行けるかと設定ファイルでの実装クラスの動作を切り替えられるかの例の話

おぉー超長いタイトルだw

簡単に言うと以下の内容を含んでいます
・Spring bootにおいてJdbc Templateをsuper classで読み取って実装クラスで使えるか
・Super classの動作を実装クラスで読み取る設定ファイルで操作できるか
・H2のデータベース… 動的に動作させる話

はいはい!
シンプルですね。
ソースとかの公開は、GitHubに上げておきます。

https://github.com/wataru775/sample_datasource_extender
はいはい、さっそく内容を行ってみます

動的にH2を動作させる話

H2データベースは組み込み型の動作が可能です…
ぶっちゃけ、メモリ上で動くって聞いて、謎が多かった。
え?DDLをいつ発行させるか? んで、デフォルトの設定とかどうしようかな?
まずは、H2をプロジェクトで読み取らせます。
pom.xml (Github pom.xml)

XMLファイルだからtextareaです。
ま、言わずもがなですな。

つぎ、設定をapplication.propertiesにいれました。
application.properties (GitHub application.properties)

spring.datasource.initialize=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

解説は… 省きます!
んで、ポイントは、ここからです。resourcesのschema.sqlが実行されます
schema.sql (Github schema.sql)

create table if not exists customer (
    id int primary key auto_increment,
    name varchar(50),
    email varchar(50)
);

ついでに、データです。
data.sql (Github data.sql)

insert into customer(name,email) values ('hoge','hoge@hoge.hoge');
insert into customer(name,email) values ('hoge2','hoge2@hoge.hoge');

ほいほい、これで毎度起動の度にメモリ上にtestdbが作成されてデータの入ったDBができあがり!
これで、testとか便利に作れるなぁー

で、次ぃー

Spring bootにおいてJdbc Templateをsuper classで読み取って実装クラスで使えるか

今、仕事で作っているプログラムにおいて複数の実装classと抽象classで構成されています。
DBの接続をおこなうのだが、JdbcTemplateを実装クラスでやってたのが、ダサい。
@Autowaredってsuperでやって参照出来るんかな?と言うわけです。

早速やってみた。
抽象クラス (抽象クラス : AbstractJDBCExtender.java )
実装クラス
Github : DBAccessService.java
Github : DBAccessService2.java

ポイントは、抽象クラスにしかJdbcTemplateがないって事です。

    @Autowired
    protected JdbcTemplate jdbcTemplate;

ちょっと次のネタを含んでいるので、分かりづらいですが、んだけですw

次ぃー

Super classの動作を実装クラスで読み取る設定ファイルで操作できるか

実は一番疑問だった。
たとえば、同じテーブルの条件で違うSQLを実行するサービスが複数あり、変換ロジック(できあがりは同じクラス形式)だけがことなるとしましょう。
実行するSQLと変換ロジックだけを実装クラスに持ち、残りの処理は抽象クラスに持たせるのが一般的でしょう。
んで、サービス名や実行SQLなどを設定ファイルに書き出せば超便利。それを実装クラス毎に作れば、便利に運用できる。
と言うわけでやってみた…
はじめは、@PropertySourceを使ってみた…
実装クラスで @PropertySource , @Autowared Enviromentを使って、読み取ると…
ま、動きますね。
しかし、複数ある場合は違います。
@Serviceの最後の@PropertySourceが採用されます!(今考えると当たり前ですが)
暫定対応として、設定ファイルにプレフィックスを設けて、やってみましたが…
ダサい!超ダサい!ってか違うファイルにする意味がない!
やりたいのは、同じサービスは同じ設定項目ということなのだ!
探しましたら、シンプルに落ち着きました。

this.getClass().getClassLoader().getResourceAsStream(filePath)

読みまーす。

    public DBAccessService() {
        super("sql/service1.properties");
    }
    public DBAccessService() {
        super("sql/service2.properties");
    }

今考えたらあたりまえですわなぁー

そんなこんなで… 眠いからこれでいっかな