una tamaño por palabras ordenar orden lista letras forma como cadenas array archivo alfabetico alfabeticamente alfabetica java hibernate hibernate-criteria

tamaño - ordenar cadenas en java



Cómo ordenar el resultado de hibernación basado en un orden específico (6)

Necesito enviar una consulta para recuperar valores que tengan un grupo específico de caracteres de la siguiente manera:

Digamos que estoy interesado en ''XX'', por lo que debería buscar cualquier campo cuyo valor comience con ''XX'' o tenga ''XX'' (espacio XX). Por ejemplo, XXCDEF , PD XXRF y CMKJIEK XX son resultados válidos.

Tengo la siguiente consulta que devuelve los resultados correctos, pero debo clasificarlos de manera que primero devuelva aquellos con XX al principio y luego otros resultados. De la siguiente manera

XXABCD XXPLER XXRFKF AB XXAB CD XXCD ZZ XXOI POLO XX

Código

Criteria criteria = session.createCriteria(Name.class, "name") .add(Restrictions.disjunction() .add(Restrictions.ilike("name.fname", fname + "%")) .add(Restrictions.ilike("name.fname", "%" + " " + fname + "%")) ) .setProjection(Projections.property("name.fname").as("fname")); List<String> names = (List<String>) criteria.list();


Ejecute dos selecciones, una filtrada para todas las cadenas que comienzan con ''XX'', la segunda filtrada para las demás.


Estúpido pero puede funcionar para tu caso.

Como obtuvo el resultado correcto, puede reconstruir los resultados de la siguiente manera:

  1. seleccione todos los resultados que comiencen con XX, póngalos en una lista L1 y realice el ordenamiento normal como Collections.sort (L1);
  2. para todos los demás resultados, haga lo mismo como Collections.sort (L2) como lista de L2
  3. Por fin, juntarlos

    List newList = new ArrayList (L1);

    newList.addAll (L2);

Tenga en cuenta. Las colecciones.sort están siguiendo el orden natural de sus elementos.



Puedes usar Predicados en criterios ... algo como esto:

public List<Name> findByParameter(String key, String value, String orderKey) CriteriaBuilder builder = this.entityManager.getCriteriaBuilder(); CriteriaQuery<Name> criteria = builder.createQuery(this.getClazz()); Root<Name> root = criteria.from(Name.getClass()); criteria.select(root); List<Predicate> predicates = new ArrayList<Predicate>(); predicates.add(builder.equal(root.get(key), value)); criteria.where(predicates.toArray(new Predicate[predicates.size()])); if (orderKey!=null && !orderKey.isEmpty()) { criteria.orderBy(builder.asc(root.get(orderKey))); } result = this.entityManager.createQuery(criteria).getResultList(); return result; }


Si no desea ordenar el resultado en la memoria, puede modificar sus criterios, le mostraré el SQL

select * from table where fname like ''XX%'' order by fname union all select * from table where fname like ''% XX%'' order by fname union all select * from table where fname like ''% XX'' order by fname

El resultado será su orden y alfabético y luego aplicará su filtro.


Con JPQL (HQL) :

select fname from Name where upper(fname) like :fnameStart or upper(fname) like :fnameMiddle order by (case when upper(fname) like :fnameStart then 1 else 2 end), fname query.setParameter("fnameStart", "XX%"); query.setParameter("fnameMiddle", "% XX%");

Con criterios

Con Criteria es mucho más complicado. En primer lugar, debe recurrir a SQL nativo en la cláusula de order . En segundo lugar, hay que enlazar la variable.

public class FirstNameOrder extends Order { public FirstNameOrder() { super("", true); } @Override public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { return "case when upper(FIRST_NAME) like ? then 1 else 2 end"; } }

La sintaxis de la expresión del caso y el nombre de la función upper deben cambiarse de acuerdo con su base de datos (y el nombre de la columna si es diferente, por supuesto).

Es fácil agregar esto a los Criteria , pero no hay API para enlazar el parámetro.

Intenté engañar a Hibernate pasando una variable no utilizada a la restricción sql personalizada para que se use efectivamente para la variable en la cláusula order by :

Criteria criteria = session.createCriteria(Name.class, "name") .add(Restrictions.disjunction() .add(Restrictions.ilike("name.fname", fname + "%")) .add(Restrictions.ilike("name.fname", "%" + " " + fname + "%"))) .setProjection(Projections.property("name.fname").as("fname")) .add(Restrictions.sqlRestriction("1 = 1", fname + "%", StringType.INSTANCE)) .addOrder(new FirstNameOrder()) .addOrder(Order.asc("fname"));

y funciona bien.

Obviamente, esta solución no se recomienda y sugiero usar JPQL para esta consulta.