- PR -

HIBERNATEについて

投稿者投稿内容
会議室デビュー日: 2006/10/17
投稿数: 13
投稿日時: 2006-10-18 00:56

このあたりか
http://www.hibernate.org/171.html
http://www.hibernate.org/hib_docs/v3/reference/en/html/persistent-classes.html#persistent-classes-dynamicmodels

動的にクラスを生成するなら
ASMかな。hibernateはなんか使ってたかな

かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-10-18 01:16
クラスは動的にいくらでも生成できるのですが、
コンパイル時のシンボル解決は静的です。

クラスをコンパイルする時点でシンボル解決ができない場合、
コンパイルエラーになりますよね?
ランタイムで生成されたクラスは、実行するまでどんな型で、
どんなシンボルを持っているかわからないのです。

一般的には、インターフェイスをあらかじめ定義しておき、
動的に生成するクラスは、そのインターフェイスを実装したクラスにします。
それならば、Class#newInstanceでインスタンス生成ができますし、
インターフェイス型の変数に代入することもできます。
つまり、シンボルが解決できるわけです。

スレ主さんがしたいのは、
1.DBにカラムhogeを追加
2.クラスをDBから動的生成
3.利用クラスは、戻り値#getHoge()を利用
って感じで考えているんですよね?
で、3のgetHogeのシンボル解決ができないと。

シンボル解決できない場合、動的に生成されたクラスをClass型で受け取って、
インスタンス生成はConstructor#newInstance/Class#newInstanceで生成します。
そして、メソッドの操作はMethod#invokeで行います。
ひと手間かけてソースを書く方が、リフレクションより面倒じゃないですよ。

これは、Javaの性質が静的言語だからであり、
実行時にシンボル解決が行われるような動的言語との違いになります。
taku
会議室デビュー日: 2006/10/16
投稿数: 8
投稿日時: 2006-10-18 02:15
狂さん>
かなりイメージに近いです!。nagiseさんの
>実装の仕方としてはjava.util.Mapの実装に
>カラム名をキーに、データをvalueにして保存するような手法で
>型不明のまま扱うことはできますが。
と一緒なのですかね。
サンプルコードの中では保存についての記述のようでしたが、DBから取得してくる方法が無かったので調べてみようと思います!(英文なのがつらいですが…)

かつのりさん>
>クラスは動的にいくらでも生成できるのですが、
非常に興味があります!今までに聞いた事がなかったので。
動的に生成する方法は狂さんの言うASMで、あらかじめ定義したインターフェースを実装したクラスを生成するのですか?(ASMもはじめて聞きました…)

スレの内容ですが
>DBにカラムhogeを追加
ではなくて新規にtableを作成です。で、そのtableにhibernateでアクセスして
saveやloadをする 
アクセスに必要なマッピングファイル、beanは前もって用意できない。
ので、動的に生成又は汎用的な型などで補う。
こんな感じです。

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-10-18 09:08
引用:

takuさんの書き込み (2006-10-18 02:15) より:
かつのりさん>
>クラスは動的にいくらでも生成できるのですが、
非常に興味があります!今までに聞いた事がなかったので。
動的に生成する方法は狂さんの言うASMで、あらかじめ定義したインターフェースを実装したクラスを生成するのですか?(ASMもはじめて聞きました…)

スレの内容ですが
>DBにカラムhogeを追加
ではなくて新規にtableを作成です。で、そのtableにhibernateでアクセスして
saveやloadをする 
アクセスに必要なマッピングファイル、beanは前もって用意できない。
ので、動的に生成又は汎用的な型などで補う。
こんな感じです。



動的に型を作るとなるとProxyクラスでしょうかねぇ。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/reflect/Proxy.html

でも、結局は静的なインターフェースのポリモーフィズムとして扱うわけですから
メソッドは事前に静的に決まっていなければいけません。

今回はテーブルを作成する段でどのような名称のカラムが作成されるか
不明なわけですから、事前の静的なメソッド定義では要件を満たせないでしょう。
結局、型不明、インターフェース不明の常にリフレクションでしか扱えない
クラスを使うでもしないといけませんが、扱いが非常に煩雑ですし、
リフレクションを毎回使うとなるとパフォーマンスも落ちるしいいことありません。
そうなるとDBのレコードを表現するクラスというものを作るという
アプローチは却下せざるをえないのではないかと思います。

それよりは単にMap使ってDBのレコードを単なるデータの塊として扱うほうが
まだいいように思います。

それを踏まえたうえで。
狂さんのリンク先には興味深いことが書かれていますね。
引用:

Chapter 4. Persistent Classes
(中略)
You may express a domain model in other ways: using trees of Map instances


マッピングする先に通常のオブジェクトではなく、
Mapを用いることができるとあります。

"4.4. Dynamic models"のところのサンプルソースでは
コード:
Session s = openSession();
Transaction tx = s.beginTransaction();

// Create a customer
Map david = new HashMap();
david.put("name", "David");

// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");

// Link both
david.put("organization", foobar);

// Save both
s.save("Customer", david);
s.save("Organization", foobar);

tx.commit();
s.close();


とまさにMapを利用してDB操作を行っていますね。
ひら
ぬし
会議室デビュー日: 2005/03/04
投稿数: 260
投稿日時: 2006-10-18 09:33
今回のケースの場合、Hibernateを使ったO/Rマッピングではなく、
ResultSetMetaDataで直接テーブル構造を読み取ってしまうのが良いと思います。


nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-10-18 13:05
引用:

ひらさんの書き込み (2006-10-18 09:33) より:
ResultSetMetaDataで直接テーブル構造を読み取ってしまうのが良いと思います。



手書きでやる場合はそうでしょうね。
そして上記サンプルはそれを肩代わりしてくれているのだと理解しています。

もっとも実証コード書いて確認したわけではないので
私の認識に誤りがあるかもしれませんが、そこは言いだしっぺのtakuさんが
検証してくれることでしょう
taku
会議室デビュー日: 2006/10/16
投稿数: 8
投稿日時: 2006-10-18 14:09
ひらさん>
そうですね〜、今回のケースの場合、Hibernateを使わない方がよさそうですね〜。私もそう思うんですが、hibernateでどこまでできるかが知りたくて。

nagiseさん>がんばって検証してみます!(できるかな…心配ではありますが)

既にDBにtableがあり、かつマッピングファイル、beanを作成すればhibernateが利用でき、簡単にデータを扱える、しかし、今回のようなケースの場合hibernateを使用するよりも、ひらさんの様な方法でデータを扱った方が楽そう。
私もそう思います。

では、プログラムの中で上記2つのケースが両方ともあった場合、どうされますか?
1つ目のケース(DBにtableがあり、かつマッピングファイル、beanを前もって用意できる状態)の場合はhibernateを使用する。
2つ目のケースの場合hibernateは使用しない。

DBのデータの扱い方が2種類あって統一されていない状態になってしまいます。
統一しなくてもいい、統一されている方がいい等などこれを読んで頂いている皆さん、
皆さんだったらどうされますか?
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-10-18 15:07
引用:

takuさんの書き込み (2006-10-18 14:09) より:
では、プログラムの中で上記2つのケースが両方ともあった場合、どうされますか?
1つ目のケース(DBにtableがあり、かつマッピングファイル、beanを前もって用意できる状態)の場合はhibernateを使用する。
2つ目のケースの場合hibernateは使用しない。

DBのデータの扱い方が2種類あって統一されていない状態になってしまいます。
統一しなくてもいい、統一されている方がいい等などこれを読んで頂いている皆さん、
皆さんだったらどうされますか?



1.ResultSetMetaDataでDBのテーブル情報を参照しながら抽象的に扱うのは結構面倒。
  肩代わりしてくれるライブラリがあるなら使いたい
2.型が決まっているところはhibernateでやっているから
  hibernateで動的モデルに対応できたら嬉しいな
3.お、なんかhibernateでやれそうじゃん。だったらhibernateで統一できるかも

という流れなのかなぁ。
hibernateで駄目なのであれば自力でResultSetMetaDataで
テーブル情報取りながら処理するしかありますまい。
(私も当初はこっちでしかできないと思っていた)
既製品があるなら使う。車輪の再発明は勉強目的以外ではやらない方針で。

DBの扱い方の件ですが、いわゆるDAOパターン
http://www.google.co.jp/search?hl=ja&q=DAO%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
を用いていればあまり気にならないかもしれません。

スキルアップ/キャリアアップ(JOB@IT)