These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Requête par l'exemple : sous-requête complexe sur historiq
PostPosted: Wed Aug 09, 2006 10:33 am 
Newbie

Joined: Wed Aug 09, 2006 7:59 am
Posts: 9
Location: Nantes - France
Bonjour,

J'utilise Hibernate 3.1.3 avec MySQL 5.0 and Oracle 9 et j'ai un problème avec une requête par l'exemple qui inclu des données historisées.
Je pense que mon contexte est un scénario classique. Mais, j'ai fait 2 jours recherche sur cet site et sur le Web sans trouver qelque chose qui m'aide vraiment.

J'ai des utilisateurs avec des postes dont l'évolution est enregistrée date par date.
Code:
table-> User  id {pk}, name, ...
table-> position id {pk}, user_id {fk}, date, status, office, ...


Dans mon modèle l'objet User a une liste de Position mais seulment la plus récente est son poste courrant.
L'utilisateur final a un formulaire pour rechercher un utilisateur donné (donc un requête par l'example s'impose).
Malheureusement ce formulaire inclu de statut qui est historisé (seul le plus récent doit être pris en compte).

Je suisen train de me casser la tête sur ce problème pour completer ma requête Criteria par l'exemple...


En premier j'ai écris ceci :
Code:
Example ex = Example.create(user);
Criteria crit = session.createCriteria(User.class).add(ex);
crit.createCriteria("positions", "pos")
    .add(Expression.eq("pos.status", userStatus);


Ca marche mais (comme c'était prévisible) ceal retourne le même utilisateur à chaque ligne de historique correspondante (même si ce n'est pas leposte leplus récent).

Voici le SQL (testé) que je cherche à traduire en Criteria :
Code:
SELECT u.*
FROM user u, position pos,
(SELECT user_id, MAX(date) AS last_date
FROM position GROUP BY user_id) last_pos
WHERE pos.user_id = last_pos.user_id
AND pos.date = last_pos.last_date;
AND u.id = pos.user_id
AND pos.status = ?
AND a.name =  ?
... //ici les autres champs du formulaire


Donc, j'ai décide de définir un sous-requête pour obtenir de poste leplus récent.
Code:
DetachedCriteria subquery = DetachedCriteria.forClass(Position.class, "last_pos");
subquery.setProjection(
   Projections.projectionList()                  
             .add( Projections.max("last_pos.date"))
         .add( Projections.groupProperty("last_pos.userAgent")
);

Example ex = Example.create(user);
Criteria crit = session.createCriteria(User.class).add(ex);
crit.createCriteria("positions", "pos")
    .add(Property.forName("pos.date").eq(subquery))
    .add(Expression.eq("pos.status", userStatus);


et j'ai obtenu l'exception suivante :
Quote:
java.lang.ClassCastException: org.hibernate.impl.CriteriaImpl$Subcriteria
at org.hibernate.criterion.SubqueryExpression.toSqlString(SubqueryExpression.java:43)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:333)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:82)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:67)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1514)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
...


Qu'est-ce que je n'ai pas bien fait ? (J'ai essayé tout un tas de variation de cela avec le même résultat)

Pour l'instant, je donne ma langue au chat.
Toute sorte d'aide, sugestions ou liens vers des exemples de code de sous-requêtes Criteria sont les bienvenus.

Merci

--
Frantz D.


Top
 Profile  
 
 Post subject: J'ai trouvé !
PostPosted: Thu Aug 10, 2006 4:29 am 
Newbie

Joined: Wed Aug 09, 2006 7:59 am
Posts: 9
Location: Nantes - France
Bonjour,

Ca y est ! Ca marche (après de 2 jours de galère supplémentaires et un bon mal de crâne ;( ).

En premier, la requête SQL peut être réécrite (et simplifiée) en utilisant une jointure explicite au lieu d'une theta-jointure, de la façon suivante :

Code:
SELECT u.*
FROM user u
INNER JOIN position pos,
ON u.id = pos.user_id
WHERE pos.date = (SELECT MAX(last_pos.date)
        FROM position last_pos
                  WHERE last_pos.userId = u.id)
AND pos.status = ?
AND a.name =  ?
... //others user form fields here

Avec la requête écrite de cette façon j'ai remarqué que la sous-requête devait être attachée à l'objet Criteria principal (et non à celui des "postes"). Mon code a donc, maintenant, l'allure suivante :
Code:
Example ex = Example.create(user);

DetachedCriteria subquery = DetachedCriteria.forClass(Position.class, "last_pos");
subquery.setProjection(Projections.max("last_pos.date"));
subquery.add(Expression.eqProperty("last_pos.userId", "u.id"));

Criteria crit = session.createCriteria(Agent.class, "a")
crit.add(ex);               
crit.createCriteria("positions", "pos");
crit.add(Subqueries.propertyEq("pos.date", subquery));
crit.add(Expression.eq("pos.status", userStatus));

return crit.list();


Voilà c'est tout.

--
Frantz D.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.