web-dev-qa-db-fra.com

Mettre en veille prolongée l'ordre avec les valeurs nulles en dernier

Hibernate utilisé avec la base de données PostgreSQL lors de la commande de desc par une colonne met les valeurs nulles supérieures à celles non nulles.

La norme SQL99 propose le mot-clé "NULLS LAST" pour déclarer que les valeurs nulles doivent être placées plus bas que non nulles.

Le comportement "NULLS LAST" peut-il être obtenu à l'aide de l'API Criteria d'Hibernate?

34
mgamer

Cette fonctionnalité a été implémentée pendant les versions Hibernate 4.2.x et 4.3.x, comme mentionné précédemment.

Il peut être utilisé comme par exemple:

Criteria criteria = ...;
criteria.addOrder( Order.desc( "name" ).nulls(NullPrecedence.FIRST) );

Les javadocs Hibernate v4.3 sont moins omissifs ici .

50
José Andias

Vous pouvez configurer "nulls first"/"nulls last" dans les propriétés de mise en veille prolongée afin qu'il soit capté par tout appel de critère par défaut: hibernate.order_by.default_null_ordering=last (ou =first).

Voir ce commit d'hibernation pour plus de détails.

9
uwolfer

Une autre variante, si vous créez SQL à la volée et n'utilisez pas l'API Criteria:

ORDER BY COALESCE (, '0') [ASC | DESC]

Cela fonctionne pour varchar ou pour les colonnes numériques.

2
Gennady Nikolaev

Voici ma mise à jour de la classe par (Pascal Thivent):

for (int i = 0; i < orderByNames.length; i++) {
    if (orderByNames[i].trim().length() > 0) {
        String orderName = orderByNames[i].trim().toLowerCase();
        if (orderName.contains("desc")) {
            orderByNames[i] = orderName.replace("desc", "desc NULLS LAST");
        } else {
            orderByNames[i] = orderName.replace("asc", "asc NULLS FIRST");
        }
    }
}

Cela résout le problème:

Cela casse si sql a une limite/décalage après la commande par - Sathish 1er avril 11 à 14:52

Voici également comment vous pouvez l'utiliser dans JPA (mise en veille prolongée):

Session session = entityManager.unwrap(Session.class);
Session nullsSortingProperlySession = null;
try {
    // perform a query guaranteeing that nulls will sort last
    nullsSortingProperlySession = session.getSessionFactory().withOptions()
        .interceptor(new GuaranteeNullsFirstInterceptor())
        .openSession();
} finally {
    // release the session, or the db connections will spiral
    try {
        if (nullsSortingProperlySession != null) {
            nullsSortingProperlySession.close();
        }
    } catch (Exception e) {
        logger.error("Error closing session", e);
    }
}

J'ai testé cela sur postgres et cela corrige le problème `` les valeurs nulles sont plus élevées que les non-nulles '' que nous avions.

2
Matt
0
Goibniu