Hibernate Computadorizada Order Critérios
Pergunta
Eu tenho uma coluna do Oracle XMLType que armazena a várias cadeias de idioma específicos. Eu preciso para construir um critério de Hibernate que as ordens nesta coluna. A fim de fazer isso, eu preciso extrair o valor com uma função de Oracle. Este critério é gerado automaticamente pelo código que tenho escrito, mas eu não posso, para a vida de mim, descobrir como extrair o valor ea ordem em que por meio da API critérios. Basicamente, o SQL gerado deve ser algo como:
SELECT EXTRACTVALUE(title, '//value[@lang="EN"]') AS enTitle
FROM domain_object
ORDER BY enTitle
Eu brincava com projeções momentaneamente, mas eles aparecem para executar uma segunda escolha. Que eu suponho que poderia causar hibernação para selecionar todos os valores e na memória tipo-los com base na projeção? Isso seria muito indesejável = \
Solução
Ok, eu encontrei a solução. Não sei se este é o melhor , por isso vou deixá-la aberta por um tempo se alguém quer fornecer uma resposta melhor / refinar a minha solução.
O que fiz foi estender org.hibernate.criterion.Order
assim:
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);
}
}
Em seguida, era apenas uma questão de dizer criteria.addOrder(LocalStringOrder.asc('prop'))
.
Outras dicas
Outra solução geral é NativeSQLOrder, consulte http: //opensource.atlassian. com / projetos / hibernate / browse / HHH-2381 . Eu não undestand, por que este recurso não está em Hibernate ainda.