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 = \

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top