Порядок вычисляемых критериев Hibernate
Вопрос
У меня есть столбец Oracle XMLType, в котором хранятся строки, специфичные для различных языков.Мне нужно создать критерии Hibernate, которые упорядочивают этот столбец.Для этого мне нужно извлечь значение с помощью функции Oracle.Эти критерии генерируются автоматически написанным мной кодом, но я не могу, хоть убей, понять, как извлечь значение и упорядочить его через API критериев.По сути, сгенерированный SQL должен выглядеть примерно так:
SELECT EXTRACTVALUE(title, '//value[@lang="EN"]') AS enTitle
FROM domain_object
ORDER BY enTitle
Я на мгновение поигрался с проекциями, но они, похоже, выполняют второй выбор.Я предполагаю, что это приведет к тому, что спящий режим выберет ВСЕ значения и отсортирует их в памяти на основе проекции?Это было бы очень нежелательно =\
Решение
Хорошо, я нашел а решение.Не уверен, что это лучший, поэтому я оставлю его открытым на некоторое время, если кто-то захочет дать лучший ответ/уточнить мое решение.
Я продлил org.hibernate.criterion.Order
таким образом:
package com.mycorp.common.hibernate;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Order;
import org.hibernate.engine.SessionFactoryImplementor;
import com.mycorp.LocalizationUtil;
public class LocalStringOrder extends Order {
private static final long serialVersionUID = 1L;
private boolean ascending;
private String propName;
public LocalStringOrder(String prop, boolean asc) {
super(prop, asc);
ascending = asc;
propName = prop;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propName);
StringBuffer fragment = new StringBuffer();
for ( int i=0; i<columns.length; i++ ) {
SessionFactoryImplementor factory = criteriaQuery.getFactory();
fragment.append( factory.getDialect().getLowercaseFunction() )
.append('(');
fragment.append("EXTRACTVALUE(");
fragment.append( columns[i] );
fragment.append(", '//value[@lang=\"" +
LocalizationUtil.getPreferedLanguage().name() +
"\"')");
fragment.append(')');
fragment.append( ascending ? " asc" : " desc" );
if ( i<columns.length-1 ) fragment.append(", ");
}
return fragment.toString();
}
public static Order asc(String propertyName) {
return new LocalStringOrder(propertyName, true);
}
public static Order desc(String propertyName) {
return new LocalStringOrder(propertyName, false);
}
}
Тогда это было просто вопрос сказать criteria.addOrder(LocalStringOrder.asc('prop'))
.
Другие советы
Другое общее решение — NativeSQLOrder, см. http://opensource.atlassian.com/projects/hibernate/browse/HHH-2381.Я не понимаю, почему этой функции еще нет в Hibernate.