Hibernate Tips
Hibernate Tips
Hibernate を使ってみて、 何となく分かってきたちょっとしたノウハウのメモ。
Field 'hoge' doesn't have a default value
原因はこのあたりにあった。
<subclass name="com.phinloda.orm.KVList" discriminator-value="Li"> <list name="value" lazy="true" cascade="none"> <key column="parent" not-null="false" /> <list-index column="lpos" /> <many-to-many column="vli" class="memolyst" /> </list> </subclass>
これはちょっとややこしいクラスの継承で発生したエラーである。 Hibernate のサンプルには、 属性を override しているようなクラスの例が出てこない。
結論だけ書く。 次のように直して解決。
<subclass name="com.phinloda.orm.KVList" discriminator-value="Li"> <list name="value" lazy="true" cascade="none"> <key column="parent" not-null="false" /> <list-index> <column name="lpos" not-null="false"/> </list-index> <many-to-many class="memolyst" /> <column name="vli" not-null="false"/> </many-to-many> </list> </subclass>
Table per class hierarchy の戦略を使うとき、 コレクションは別テーブルにマッピングされる。 先の例では、 テーブルを特に指定していないから、 value というテーブルが自動的に生成されてしまう。 名前を指定したい場合は、 次のようにして明示的に指定する。
<list name="value" table="listtable" lazy="true" cascade="none"> ...
(2006-06-16)
longtext
MySQL を使うときに、 type を text と指定すると、 65535 文字まで使えるようなカラムができる。 longtext を使いたい場合はどう指定するかというと、 mapping の property のところに length を指定すればいい。
<joined-subclass name="com.phinloda.orm.KVText" table="kvtx" extends="memolyst"> <key column="id" /> <property name="value" type="text" column="value" length="2147483647" /> </joined-subclass>
このように length を指定すると、 type を text と指定しても、 MySQL の longtext を使うような SQL を生成してくれる。
create table kvtx (id integer not null, value longtext, primary key (id));
(2006-06-03)
DISTINCT
n+1 問題を解決するために Collection を left join すると、 同じ内容の行が複数 select されてしまう。 これは仕様で、 マニュアルには set にマッピングする方法が紹介されている。
Query mothersWithKittens = (Cat) session.createQuery( "select mother from Cat as mother left join fetch mother.kittens"); Set uniqueMothers = new HashSet(mothersWithKittens.list());
Note that queries that make use of eager fetching of collections usually return duplicates of the root objects (but with their collections initialized).
You can filter these duplicates simply through a Set.
(10.4.1. Executing queries)
超訳: コレクションをイーガーフェッチで持ってくるようなクエリを使うと、 内容は一発で確かに取得できるのだが、 基本的に、結果に同じ内容の行が含まれてしまう。 重複を除去したいなら、Set を使うのが簡単である。
それなら単に distinct を使えばいいのではないか? ところが、次のような HQL を使っても思った結果が得られない。
select distinct hoge from HogeClass as hoge left join fetch hoge.values;
かなりハマった。 結論。 3.1 だとダメ。 この機能は 3.2.0 alpha1 から使えるようになったので、 それ以降のバージョンにしてみるとよい。
(2006-05-08)
foreign key
MySQL、Oracle で、 foreign key constraint fails というエラーメッセージが出ることがある。
MySQL の場合、
このエラーを回避するために、 最後の手段として、foreign key を生成しないという裏技がある。 これは、 key の属性に foreign-key="none" を指定することで実現できる。
(2006-03-27)