Hi,
I can't get the "order by" on criteria searches to work with computed columns on DB2. The following works well with MySQL.
I have two classes in my model, Foo and Bar.
Foo.java:
Code:
package model;
public class Foo {
int id;
private int val;
private Bar bar;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
Bar.java:
Code:
package model;
import java.util.List;
public class Bar {
private int id;
private List foos; // List of Foo, mapped with bag
private int minimum; // Minimum Foo.val in list, mapped with formula
private int maximum; // Maximum Foo.val in list, mapped with formula
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List getFoos() {
return foos;
}
public void setFoos(List foos) {
this.foos = foos;
}
public int getMaximum() {
return maximum;
}
public void setMaximum(int maximum) {
this.maximum = maximum;
}
public int getMinimum() {
return minimum;
}
public void setMinimum(int minimum) {
this.minimum = minimum;
}
}
Foo.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="model">
<class name="Foo" table="foo_table">
<id name="id" type="integer" unsaved-value="0" column="FOO_ID">
<generator class="native"></generator>
</id>
<many-to-one name="bar" class="Bar" column="BAR_ID" index="IX_BAR_VAL"/>
<property name="val" not-null="true">
<column name="VAL" />
</property>
</class>
</hibernate-mapping>
Bar.hbm.xml,
note the formula propertiesCode:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="model">
<class name="Bar" table="bar_table">
<id name="id" type="integer" unsaved-value="0" column="BAR_ID">
<generator class="native"></generator>
</id>
<property name="minimum">
<formula>
( SELECT min( foo.val ) FROM foo_table foo WHERE foo.bar_id = bar_id )
</formula>
</property>
<property name="maximum">
<formula>
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = bar_id )
</formula>
</property>
<bag name="foos" inverse="true">
<key column="BAR_ID" />
<one-to-many class="Foo" />
</bag>
</class>
</hibernate-mapping>
hibernate.cfg.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- DB2, Database connection settings -->
<property name="connection.driver_class">COM.ibm.db2.jdbc.app.DB2Driver</property>
<property name="connection.url">jdbc:db2:BUG_TEST</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="current_session_context_class">thread</property>
<property name="connection.isolation">1</property>
<property name="connection.pool_size">20</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="cache.use_second_level_cache">false</property>
<property name="cache.use_query_cache">false</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<mapping resource="model/Foo.hbm.xml"/>
<mapping resource="model/Bar.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Using the test application below I get an error.
Note how I order on one of the computed properties.Code:
package app;
import java.util.Iterator;
import java.util.List;
import model.Bar;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import util.HibernateUtil;
public class Test {
public List getBars() {
List result;
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Bar.class);
criteria.addOrder( Order.asc( "maximum" ) );
result = criteria.list();
transaction.commit();
return result;
}
public static void main(String[] args) {
Test test = new Test();
List bars = test.getBars();
System.out.println("Result:");
for (Iterator itr=bars.iterator(); itr.hasNext(); ) {
Bar bar = (Bar)itr.next();
System.out.println( "bar_id="+bar.getId()+" "+
"min="+bar.getMinimum()+" "+
"max="+bar.getMaximum()
);
}
}
}
I get the following output:
Code:
Hibernate: select this_.BAR_ID as BAR1_1_0_,
( SELECT min( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula0_0_,
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula1_0_ from bar_table this_ order by
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
asc
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.doList(Loader.java:2148)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
at org.hibernate.loader.Loader.list(Loader.java:2024)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1533)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
at app.Test.getBars(Test.java:23)
at app.Test.main(Test.java:31)
Caused by: COM.ibm.db2.jdbc.DB2Exception: [IBM][CLI Driver][DB2/NT] SQL0206N "THIS_.BAR_ID" is not valid in the context where it is used. SQLSTATE=42703
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(Unknown Source)
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(Unknown Source)
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.check_return_code(Unknown Source)
at COM.ibm.db2.jdbc.app.DB2PreparedStatement.execute2(Unknown Source)
at COM.ibm.db2.jdbc.app.DB2PreparedStatement.executeQuery(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:139)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1669)
at org.hibernate.loader.Loader.doQuery(Loader.java:662)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.doList(Loader.java:2145)
... 7 more
The problem is with "order by
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id =
this_.bar_id )
asc"
Running these two queries manually works fine:
Code:
select this_.BAR_ID as BAR1_1_0_,
( SELECT min( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula0_0_,
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula1_0_ from bar_table this_
order by
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = bar_id )
asc
Code:
select this_.BAR_ID as BAR1_1_0_,
( SELECT min( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula0_0_,
( SELECT max( foo.val ) FROM foo_table foo WHERE foo.bar_id = this_.bar_id )
as formula1_0_ from bar_table this_
order by formula1_0_ asc
Any ideas? Is this a bug in DB2Dialect?
Many thanks!
/MÃ¥rten