daybreaksnow's diary

私を私と呼びたい

[Hibernate]sqlRestriction使用時のエイリアス名の解決方法

sqlRestrictionでは、ルートとなるエンティティのエイリアスは{alias}で取得できるが、
joinしたエンティティのエイリアスは取得できない。

Criteria criteria = session.createCriteria(Bid.class);
criteria.createAlias("item", "aliasItem");
criteria.add(Restrictions.sqlRestriction("{alias}.amount = 1"));
criteria.add(Restrictions.sqlRestriction("aliasItem.name = 'hoge'"));

発行されるSQL

select this_.bid_id as bid1_3_1_, this_.item_id as item2_3_1_, this_.amount as amount3_1_, 
 aliasitem1_.item_id as item1_4_0_, aliasitem1_.name as name4_0_
from public.bid this_
inner join public.item aliasitem1_
 on this_.item_id=aliasitem1_.item_id
where this_.amount = 1 and aliasItem.name = 'hoge'

上記のとおり、ソースコード上で"aliasItem"と指定したエイリアス名が、実際に発行されるSQLではaliasitem1_となってしまう。
そのため、このコードは実行時に例外が発生する。


この問題を解決するには、createAliasではなく、createCriteriaを使えばよい。
参考URL:
http://ch-express.blogspot.jp/2008/06/hibernate-criteria-sqlrestriction-alias.html


上記のSQLを書き換えた例

Criteria criteria = session.createCriteria(Bid.class);
criteria.add(Restrictions.sqlRestriction("{alias}.amount = 1"));
Criteria subCriteria = criteria.createCriteria("item");
subCriteria.add(Restrictions.sqlRestriction("{alias}.name = 'hoge'"));

発行されるSQL

select this_.bid_id as bid1_3_1_, this_.item_id as item2_3_1_, this_.amount as amount3_1_,
 item1_.item_id as item1_4_0_, item1_.name as name4_0_, 
from public.bid this_ 
inner join public.item item1_
 on this_.item_id=item1_.item_id 
where this_.amount = 1 and item1_.name = 'hoge'


createAliasとcreateCriteriaを混ぜることも可能。

Criteria criteria = session.createCriteria(Bid.class);
criteria.createAlias("item", "aliasItem");
Criteria subCriteria = criteria.createCriteria("item.mapping");
subCriteria.add(Restrictions.sqlRestriction("{alias}.id = 1"));