Pergunta

Eu estou tentando fazer consulta paginação resultado com hibernate e displaytag e objetos DetachedCriteria Hibernate está fazendo o seu melhor para ficar no caminho. Deixe-me explicar ...

A maneira mais fácil de fazer a paginação com displaytag parece estar implementando a interface PaginatedList que tem, entre outros, os seguintes métodos:

/* Gets the total number of results. */
int getFullListSize();

/* Gets the current page of results. */
List getList();

/* Gets the page size. */
int getObjectsPerPage();

/* Gets the current page number. */
int getPageNumber();

/* Get the sorting column and direction */
String getSortCriterion();
SortOrderEnum getSortDirection();

Estou pensando em jogar minha implementação PaginatedList um critério objeto e deixá-lo trabalhar junto theese linhas ...

getFullListSize() {
    criteria.setProjection(Projections.rowCount());
    return ((Long) criteria.uniqueResult()).intValue();
}

getList() {
    if (getSortDirection() == SortOrderEnum.ASCENDING) {
        criteria.addOrder(Order.asc(getSortCriterion());
    } else if (getSortDirection() == SortOrderEnum.DECENDING) {
        criteria.addOrder(Order.desc(getSortCriterion());
    }
    return criteria.list((getPageNumber() - 1) * getObjectsPerPage(),
                         getObjectsPerPage());
}

Mas isso não funciona, porque o addOrder() ou as chamadas setProjection() modificar os critérios de objeto tornando-in-utilizável para as chamadas sucessivas. Eu não sou inteiramente certo da ordem das chamadas, mas a db gera um erro em getFullListSize() tentando fazer um "select count(*) ... order by ...", que é obviamente errado.

Eu acho que eu poderia corrigir isso criando um objeto de meu próprio para manter o controle de condições de consulta e reconstruir o objeto Criteria para cada chamada, mas que se sente como reinventar uma outra roda. Existe uma maneira mais inteligente, possivelmente copiando os critérios inicialmente aprovadas e que trabalham nessa cópia?

Atualização : Parece que getList é chamado pela primeira vez, e getFullListSize é chamado várias vezes depois, então, assim que há uma ordenação passada, getFullListSize falhará. Não faria sentido para bater o db apenas uma vez (em getList eu diria) e cache os resultados, sem a necessidade de copiar / redefinir o objeto Criteria, mas ainda assim ...

Update (de novo) : Esqueça isso, depois de já ter feito o count eu não posso fazer o select, e vice-versa. Eu realmente preciso de dois objetos Criteria distinto.

Foi útil?

Solução

Bem, DetachedCriteria são Serializable, então você tem built-in (se deselegante) apoio clone profundo. Você pode serializar os critérios iniciais para um byte [] uma vez em construção, em seguida, desserializar-lo cada vez que você quiser usá-lo.

Outras dicas

Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);

Será que efetivamente "reset" os critérios entre a projeção rowCount e execução da própria critérios.

Gostaria de ter certeza seu pedido não foi adicionado antes de fazer o rowCount, vai retardar as coisas. Minha implementação de PaginatedList SEMPRE executa uma consulta de contagem antes de olhar para os resultados, por isso ordenação não é um problema.

http://weblogs.asp.net/stefansedich/archive/2008/10/03/paging-with-nhibernate-using-a-custom-extension-method-to-make -it-easier.aspx

Neste post eu avistou um método CriteriaTransformer.clone.

Isso deve copiar o objeto critérios.

Você também pode definir a projeção do seu método GetList.

Woops Eu não percebi que você estava referindo-se a java hibernate. De qualquer forma, este http://forum.hibernate.org/viewtopic.php?t=939039

post do fórum deve ser capaz de responder a sua pergunta.

feio como pode ser acabei usando o truque de serialização. Eu só seriar o objeto DetachedCriteria para um array de bytes na construção do objeto PaginatedList e de serialize-lo quando necessário. Ouch.

Outra pena coisa a tentar:

implementar um DAO genérico como o sugerido no de hibernação local e passá-lo para o PaginatedList objecto, juntamente com um objecto de restrições. O objeto PaginatedList seria então fazer algo parecido

Criteria.forClass(myDAO.getPersistentClass())
        .add(myRestrictions)
        .addOrder(<someOrder>)

e

Criteria.forClass(myDAO.getPersistentClass())
        .add(myRestrictions)
        .setProjection(Projections.rowCount());

Ainda não tentei isso ainda, mas deve funcionar.

public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
   var dummy = criteria.ToByteArray();
   return dummy.FromByteArray<DetachedCriteria>();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top