Exécuter des requêtes à travers des fragments peut être difficile. Dans ce chapitre nous parlerons de ce qui fonctionne, ce qui ne fonctionne pas, et ce que vous pouvez faire pour éviter les ennuis.
Comme nous en avons parlé dans le chapitre sur les limitations, nous n'avons pas encore d'implémentation complète de l'API Hibernate Core. Cette limitation s'applique à ShardedCriteriaImpl, qui est une implémentation de l'interface Criteria prenant en compte les fragments. Dans ce chapitre nous n'entrerons pas dans les détails des choses spécifiques qui n'ont pas été implémentées. Nous allons plutôt discuter des types de requêtes Criteria qui sont problématiques dans un environnement fragmenté.
Dis simplement, les requêtes qui effectuent des tris posent problème. Pourquoi ? Parce que nous ne pouvons pas retourner une liste proprement triée sans la capacité de comparer une valeur de la liste à toute autre valeur de la liste, et la liste entière n'est pas disponible jusqu'à ce que tous les résultats des requêtes individuelles aient été collectés dans la partie applicative. Le tri a besoin de s'effectuer à l'intérieur d'Hibernate Shards, et pour que cela arrive, nous demandons à tous les objets retournés par une requête Criteria avec une clause "order-by" d'implémenter l'interface Comparable. Si le type des objets que vous retournez n'implémente pas cette interface, vous aurez une exception.
Les clauses "distinct" posent aussi problème. Tellement de problèmes, en fait, que pour le moment nous les prenons même pas en charge. Désolé pour ça.
D'un autre côté, alors que "distinct" et "order-by" posent problèmes, les agrégats fonctionnent bien. Considérez l'exemple suivante :
// récupère la moyenne de toutes les températures enregistrées depuis jeudi dernier Criteria crit = session.createCriteria(WeatherReport.class); crit.add(Restrictions.gt("timestamp", lastThursday)); crit.setProjection(Projections.avg("temperature")); return crit.list();
Dans un environnement avec un seul fragment, cette requête peut obtenir une réponse facilement, mais dans un environnement avec plusieurs fragments c'est un peu plus embêtant. Pourquoi ? Parce qu'obtenir la moyenne de chaque fragment n'est pas suffisant pour calculer la moyenne à travers tous les fragments. Pour calculer ce morceau d'informations, nous n'avons pas seulement besoin de la moyenne mais du nombre d'enregistrements de chaque fragment. C'est exactement ce que nous faisons, et l'impact sur les performances (faire un "count" supplémentaire dans chaque requête) est probablement négligeable. Maintenant, si nous voulions la médiane, nous aurions des problèmes (ajouter le "count" à la requête ne fournirait pas assez d'informations pour réaliser le calcul), mais pour le moment Criteria n'expose pas de fonction médiane, donc nous traiterons ça lorsque cela arrivera et sera un problème.
Notre prise en charge de HQL n'est pas, pour le moment, aussi bon que la prise en charge des requêtes Criteria. Nous n'avons pas encore implémenté d'extensions à l'analyseur lexico-syntaxique de requêtes, donc nous prenons pas en charge "distinct", "order-by", ou les agrégats. Cela signifie que vous pouvez seulement utiliser HQL pour des requêtes très simples. Vous feriez probablement mieux d'éviter le HQL de cette version si vous le pouvez.
Le seul composant de votre stratégie de fragmentation qui est consulté lors de l'exécution d'une requête (Criteria ou HQL) est la ShardAccessStrategy. ShardSelectionStrategy est ignorée parce qu'exécuter une requête ne crée pas de nouvel enregistrement dans la base de données. ShardResolutionStrategy est ignorée parce qu'actuellement nous partons du principe que vous voulez toujours que votre requête soit exécutée sur tous les fragments. Si ce n'est pas le cas, la meilleure chose à faire de transtyper votre Session en une ShardedSession et d'en extraire la Session spécifique au fragment dont vous avez besoin. Maladroit, mais ça fonctionne. Nous proposerons une meilleure solution dans une prochaine version.