Hibernate 入門寸前
直前と寸前ではどっちが際どいのでしょうか? どっちでもいいですか,そうですよね.とりあえずここでは寸前のほうが際どいということでよろしくお願いします(何を?).
さて,入門直前でHibernateを使う上で必要なものはだいたい分かったので,まずは最初の一歩を踏み出してみたいと思います.おっと,踏み出してしまうと寸前ではなくなるので,最初の一歩を踏み出そうとしてみようと思います.
ということで永続クラスとかテーブルとか作らなきゃいけないわけですが,始から大掛かりなことはしたくないので,既存のテーブルを使う方向で考えてみます.OracleのDUAL表を使うなんていいかなぁ? カラム1個だし主キーはないし.(^^;
なぁんて考えてDual
クラスを作ったりしてみたのですが...
主キーがない場合のマッピングファイルの書き方が分かりませんでした.(;_;)
無念だ.
しょうがないので,HSQLDBのDatabase ManagerからInsert test dataすると作られるcustomer
表を使ってみることにします.テーブルはもちろんデータまで用意してもらえるのでラクチン.
customer
テーブルはこんな感じ.
カラム名 | 型 | 主キー |
---|---|---|
id | integer | ○ |
firstname | varchar | |
lastname | varchar | |
street | varchar | |
city | varchar |
こんな感じ.
package study; public class Customer { private int id; private String firstName; private String lastName; private String street; private String city; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String toString() { return Integer.toString(id) + " : " + firstName + " " + lastName + ", " + street + " " + city; } }
次にcustomer
テーブルとstudy.Customer
クラスのマッピングファイル,study/Customer.cfg.xml
を作ります.リファレンスやら「オープンソースJavaプロダクツ (isbn:4774119989)」やら眺めて書いてみるテスト.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > <hibernate-mapping> <class name="study.Customer" table="customer"> <id name="id"> <generator class="increment"/> </id> <property name="firstName"/> <property name="lastName"/> <property name="street"/> <property name="city"/> </class> </hibernate-mapping>
<generator>
要素に何を指定すればいいのかよく分かっていないのですが,主キーの生成に使われるとのこと.今回はもうテーブルにデータが入っているので insert
する気はないし,一番無害そうなやつを書いてみるテスト.
それから,JDBCの接続情報などを記述した hibernate.cfg.xml
を使うと楽っぽいので,これも書いてみるテスト.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd" > <hibernate-configuration> <session-factory> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.url">jdbc:hsqldb:hsql://localhost:9001</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <property name="dialect">net.sf.hibernate.dialect.HSQLDialect</property> <property name="show_sql">true</property> <mapping resource="study/Customer.hbm.xml"/> </session-factory> </hibernate-configuration>
使用するマッピングファイルもここで定義しちゃうんですね.
さて,後はHibernateを使うのみ!
やるべきことは,Configuration
に hibernate.cfg.xml
を渡して初期化して,そこから SessionFactory
を取ってきて,そこからさらに Session
を取ってきて,その問合せメソッドである find(String)
を呼べば,永続クラス(この場合はもちろんCustomer
)の List
が返ってくるらしい.ふむふむ.
Session#find(String)
に渡す文字列は,SQLの from
以降でいいっぽい.
ということで実行用のクラスを作成!
package study; import java.util.Iterator; import java.util.List; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.cfg.Configuration; public class Main { public static void main(String[] args) { try { Configuration config = new Configuration(); SessionFactory factory = config.configure().buildSessionFactory(); Session session = factory.openSession(); List customers = session.find("from customer"); Iterator it = customers.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } catch (Throwable e) { e.printStackTrace(); } } }
そして実行!!
Hibernate: select from - SQL Error: -11, SQLState: 37000 - Unexpected token: FROM in statement [select from] - SQL Error: -11, SQLState: 37000 - Unexpected token: FROM in statement [select from] - Could not execute query java.sql.SQLException: Unexpected token: FROM in statement [select from] ・ ・ ・
ぐはぁっ,なぜに? なぜにSQLが select from
だけなの?
うーみゅ,まさか入門寸前でいきなり躓くとは... 無念だ.
こういう場合はどこを調べればいいんだろう?
...
リファレンスの「第9章 Hibernate Query Language」に気になること発見.
クエリは、Javaクラスやプロパティ名を除いて、大文字・小文字の区別はありません。
なんですと? クエリにJavaクラス? えぇっ? もしかして,from
の後ろはテーブル名じゃなくてJavaのクラス名なの? うひゃー.
ってことは Session#find(String)
の引数は "from customer"
ではなくて "from Customer"
にしなきゃいけないってこと? あれ,"from study.Customer"
か?
両方やってみました.どちらでもよかったっぽい.いずれにしても
Hibernate: select customer0_.id as id, customer0_.firstName as firstName, customer0_.lastName as lastName, customer0_.street as street, customer0_.city as city from customer customer0_ 0 : Laura Steel, 429 Seventh Av. Dallas 1 : Susanne King, 366 - 20th Ave. Olten 2 : Anne Miller, 20 Upland Pl. Lyon ・ ・ ・
という具合に全件取得することが出来ました.
そうか,Hibernateの問合せ言語がSQLじゃなくてHQLとなっているのはそういうことなのか... 油断したなぁ.心より恥じる.
ともあれ(JW),無事にHibernateはじめの一歩を体験することが出来ました.もとい,その寸前まで体験出来ました.よかった.ここでクリアできなかったら,寸前より際どい言葉を捜さなきゃいけないところだったよ.せーふ.
ということで,次回から本格的に入門していきたいと思うのですが,いまだに進め方がイメージできていません.Springの時はリファレンスの通りに学習したのですが,あれはSpringが単純なコンテナの上位にいろいろな機能が乗っかっていたからできたことで,Hibernateでもそれができるのでしょうか? 今回みたいに簡単なことをするのでさえ9章まで見に行ったわけで... 困ったにゃぁ.
いいや,明日考えよう.