ここでは、SpringJDBCとはどんな機能かを簡単に見ていこうと思います。
SpringJDBCは、JavaのオブジェクトとDBのテーブルの間を仲立ちする機能です。
一般的にはO/Rマッピングといいます。
総称を言ったところで何もわからないのでもう少し具体的に行きましょー
【使用例】
少し準備のコードが必要ですが、ここでは準備を無視して使用例だけ見てみましょう。
<取得する情報>
会員情報クラス(Member)を取得することを考えます。
<①複数の結果を取得する場合の例>
String sql = "select * from member ";
List<Member> memberList = this.simpleTemplate.query(
sql, new MemberRowMapper()
);
<②1レコードの結果を取得する場合の例>
String sql = "select * from member where id=:id";
Map key = new HashMap();
key.put("id", "id0006");
Member member = this.namedParameterTemplate.query(
sql, key, new MemberRowMapper()
);
【説明】
①も②も同じMemberRowMapper(自作クラス)を引数にしています。
つまり、再利用しています。
こんな感じで、ResultSetからMemberオブジェクトへのマッピングが簡単になり、
1つマッピングクラスを作れば、Listも1つのオブジェクトも取得できるのです。
しかもコードの可読性が高くなっています。
もうひとつの注目点は、②の:idの部分。
そのあと、key.put()でidの値を設定しています。
なんとなく想像つくと思いますが、この値でSQL文が置き換わるのです。
普通、jdbcでは?を置き換えできますが、数が多くなるとわけが分からなくなります。
それを解決してくれます。
結局、②のSQL文は以下のようになります。
select * from member where id='id0006'
地味な機能ですが、結構便利ですよ!
【機能で重要なこと】
SpringJDBCは地味な感じですが、裏でいろいろやっています。
そのうちのひとつについて、書いておきます。
実は、データソースをプールしているんです。
しかも、スレッドごとに1つデータソースを割り当ててくれます。
ですので、何も気にせずにSpringJDBCからデータソースを取得しても、
同じスレッドなら同じデータソースにアクセスできます。
もしこれをSpringJDBCを使用せずに行うと、トランザクションの最初にデータソースを取得して、
メソッドを呼び出すたびに引数に入れて引き回さないといけません。
そうしないと、トランザクションなどを制御できないからです。
このあたりは見落としがちなのですが、真面目にやろうとするとかなりコードのルールを作らないといけません。
1人ならいいのですが、複数で開発するときなどは大変です。
ぜひともSpringJDBCを使って、効率化しましょう!
【トランザクションについて】
さらにうれしい機能が!
トランザクションの管理をSpringの設定ファイルだけでできます!
どんな感じかというと、例外が発生したときにrollbackし、例外がなければcommitするんです。
これは指定のメソッドに対して、メソッドの最初でトランザクション開始し、メソッドを抜けるときにトランザクションを終了します。(AOPの機能なので、以下のようにAOPの設定の仕方と同じになります)
メソッド指定例: execution(* business.service..*(..))
もうひとつ!
では、指定のメソッドがさらにその中で、Springで設定されたメソッドを呼んだ場合どうなるんでしょう?
例えば、以下のようなケースです。
Springでのトランザクション: AメソッドとBメソッドに対して設定。
void A(){ B(); ... }
このような場合、一番外側のメソッドに対してだけトランザクションが実行されるんです。
上記の場合、A( )の開始でトランザクションが開始されて、A( )を抜けるときにトランザクションを終了します。
B( )のメソッド内部では、トランザクションの開始はしません!
SpringJDBCを使用しないと、A、Bのメソッド内それぞれでトランザクションの開始とrollbackを記述しないといけませんよね?これって大変です。
しかも、A、Bのメソッドは再利用の観点から言うと、それぞれ独立でも使用したいし、上の例のように内部からさらに呼び出したいケースがあると思います。
そうすると、独立で使用するのか?内部から呼び出すのかのフラグを引数に持たないと実現できません。
このケースに対応するにはSpringのトランザクションを使用しないと難しいですよね?
==このトランザクションの機能はかなり有用です!!
Oracleのようにトランザクションの入れ子ができると、ある程度上記の入れ子でメソッドが呼ばれる場合も
対処できます。
しかし、Postgresはトランザクションの入れ子ができません!!
そういうDBもあるのでそういう意味でもかなり有用な機能です!
【try~catchについて】
普通、JDBC絡みの処理を書くと、try~catchを記述しないといけません。
なぜならJDBC関連のメソッドがキャッチしないといけない例外をthrowするからです。
意外とこれは面倒です。
しかしSpringJDBCを使用すると、例外をすべてRuntimeExceptionに変換してくれます!
つまり、try~catchをDao内で書く必要がなくなります!
これは可読性が上がるとともに、記述が楽になります。
【補足】
Hibernateは有名なO/Rマッピングで、かなり機能が多いし強力です。
SQL文を書かずに、設定ファイルだけでDBとの連携ができるのは魅力です。
いい機能だと思います。
しかし、DBの設計にやたらと口を出してきます。
例えば、必ず一意のIDをテーブルに持たせないといけない。それはprimaryキーにしないといけない。
など。
しかも、Hibernateを使用すると、勝手にDBのindexなどを変えてしまうのです。
また、複雑にデータを取る場合、SQL文を自分で書くこともできるのですが
ちょっと複雑になるとすぐに、「設定ファイルだけでは対応できませーん」って、悲鳴を上げるので、大きなシステムを扱う場合、結局SQL文を書かないといけなくなります。
正直、趣味の問題ですが、自分はあまりHibernateの考え方が得意ではありません。
それよりも、シンプルですが、SQL文が見え、コードが分かりやすい、SpringのJDBCの方が好きです。
一度、勉強してみる価値はあると思います!
是非、使ってみましょう
参考:
・SpringJDBCで作成したDaoとビジネスロジックを連携するには?
・DBからデータを取得するには?(SimpleJdbcTemplate のサンプル)
・DBからデータを取得するには?(NamedParameterJdbcTemplateのサンプル)
・NamedParameterJdbcTemplateをうまく使うには?