2010-04-07 20 views
2

Je construire un Hibernate Criterion, en utilisant une sous-sélection comme suitNULL manipulation avec subselect API Critères Hibernate

DetachedCriteria subselect = 
    DetachedCriteria.forClass(NhmCode.class, "sub"); // the subselect selecting the maximum 'validFrom' 
subselect.add(Restrictions.le("validFrom", new Date())); // it should be in the past (null needs handling here) 
subselect.add(Property.forName("sub.lifeCycle").eqProperty("this.id")); // join to owning entity 
subselect.setProjection(Projections.max("validFrom")); // we are only interested in the maximum validFrom 

Conjunction resultCriterion = Restrictions.conjunction(); 
resultCriterion.add(Restrictions.ilike(property, value)); // I have other Restrictions as well 
resultCriterion.add(Property.forName("validFrom").eq(subselect)); // this fails when validFrom and the subselect return NULL 

return resultCriterion; 

Il fonctionne ok jusqu'à présent, mais la restriction à la dernière ligne avant l'instruction de retour est faux lorsque validFrom et subselect aboutissent à NULL.

Ce dont j'ai besoin, c'est d'une version qui gère ce cas comme vrai. Peut-être en appliquant une NVL ou coalesce ou similaire.

Comment faire?

Mise à jour: ----------------------------

Péters idée avec les résultats de sqlRestriction dans une clause where comme celui-ci :

 ... 
     and (
      nhmcode1_.valid_from = (
       select 
        max(sub_.valid_from) as y0_ 
       from 
        nhm_code sub_ 
       where 
        sub_.valid_from<=? 
        and sub_.lc_id=this_.id 
      ) 
      or (
       nhmcode1_.valid_from is null 
       and sub.validFrom is null 
      ) 
     ) 
     ... 

qui entraînent à leur tour dans:

ORA-00904: "SUB _" "validFrom". ungültiger Bezeichner

le message d'erreur qui signifie 'identifiant non valide'

+0

Vous venez de trouver ceci: http://www.opendocs.net/javadoc/hibernate/3/org/hibernate/criterion/Subqueries.html ... peut-être que cela est utile? –

Répondre

0

Il semble vraiment que ce soit une limitation supplémentaire de l'API Criteria.

J'ai trouvé qu'il n'est pas vraiment difficile de créer votre propre critère (ou ensemble de critères) pour ce genre de chose.

Le plus gros problème est que vous devrez vous passer de toute documentation. Prenez une implémentation qui est similaire à ce que vous voulez faire. Tweek, voir ce que SQL il génère, rincer et répéter.

Pas marrant, mais ça marche.

Désolé, l'implémentation n'est pas disponible pour le problème dans la question.

5

Vous pouvez essayer quelque chose comme ça au lieu de la ligne problématique:

resultCriterion.add(
    Restrictions.or(
    Restrictions.and(
     Restrictions.isNull("validFrom"), 
     Restrictions.sqlRestriction("sub.validFrom is null") 
    ), 
    Property.forName("validFrom").eq(subselect) 
) 
); 

Cela peut ne pas tout de suite, mais je l'espère aide.

+0

Bonjour Peter, malheureusement ce n'est que 50% de la solution. Pour correspondre à mes besoins, il doit être: resultCriterion.add (Restrictions.ou Restrictions.et ( Restrictions.isNull ("validFrom"), Restrictions.isNull (sous-sélection)), Property.forName ("validFrom"). eq (sous-sélection))); mais isNull ne peut pas prendre une sous-requête (et si c'était le cas, elle dupliquerait probablement la suquery dans le sql qui serait moche, bien que cela ne me tuerait pas). –

+0

@Jens Je viens de mettre à jour l'exemple pour (espérons-le) faire face à cela. –