C'est plus d'un design que la question de la mise en œuvre et cela va être long, alors supporte-moi. Il est préférable d'expliquer avec un exemple: p>
Disons que j'ai une entité d'affaires appelée produit b> avec un tas de propriétés ( Nom B>, Prix B>, Vendeur B>, etc ...). p>
Il est représenté par une interface ( produit b>) et la mise en œuvre ( productimpl b>, mappée dans l'hibernate) ainsi que l'interface de service de base de CRUD ( Produitservice B>) et la mise en œuvre ( ProduitserviceImpl b>).
Produit B> et Produitservice B> sont exposés comme API, leurs implémentations ne sont pas.
p>
Je souhaite ajouter un Liste des chiffroducts (critères QueryCriteria) b> Méthode à Produitservice B> qui rendrait une liste de produits satisfaisants de critères donnés.
Les exigences sont:
p>
La question est donc ce que l'interface QueryCriteria B> est-elle utilisée par une telle méthode? Je peux penser à 3 solutions et je n'aime pas l'un d'entre eux: p>
Toute commentaires sur la validité des approches ci-dessus ou des doigts croisés - des solutions élégantes simples qui ne me sont pas produites seraient très appréciées. p>
P.s. Dans mon cas particulier, tous les clients de l'API sont internes et "semi-fiducies" - c'est-à-dire que je ne suis pas aussi préoccupé par une personne qui tente de briser délibérément quelque chose comme avec une programmation médiocre résultant du produit cartésien de 5 tables :-) Cependant, «D Soyez agréable de proposer une solution qui résisterait à l'exposition de l'API au public. P>
Produit.Price GT 50.0 Code>) Li>
produit.vendor.name = "Oracle" CODE>) LI>
Commander par produit.vendor.name Desc, produit.Price ASC " code>) LI>
produit.vendor.name = "Microsoft" code>, la requête dans (2) ci-dessus doit produire un ensemble de résultats vide. li>
ol>
6 Réponses :
Ce n'est jamais une bonne idée d'exposer ces détails de la mise en œuvre. Vous êtes limité à cette bibliothèque à partir de là. Pire, tout changement d'API de la bibliothèque couse une API que je change de votre service. Toute considération de sécurité laissée derrière ... p>
Qu'en est-il des noms de propriétés de haricot utilisés dans les critères (un triplé de nom de propriété, Enum avec moins, égal et plus de valeur). Avec un wrapper de haricot sur votre modèle, vous pouvez transformer cela en un critère hiberné. P>
Il sera également possible de transformer ces noms de propriété vers une nouvelle version après un changement de modèle. P>
Je me rends compte que vous pouvez tout résumé, mais il y a une ligne quelque part - je suis à peu près sûr que je ne vais pas changer de couches d'orme et je doute que Hibernate API changera de manière incompatible dans un avenir prévisible. Cela dit, je n'ai pas suggéré d'exposer une API hétéroplantée dans l'une des 3 solutions proposées ci-dessus. Je ne sais pas ce que vous vouliez dire par "Wrapper modèle de haricot", mais la propriété / la comparaison / la valeur est juste un cas simple. Une fois que vous avez ajouté des comparaisons, des collections, etc., vous finirez par réécrire l'API de l'ensemble de la critère.
hmm - question intéressante. P>
Après avoir réfléchi, écrire votre propre interface de critères est probablement la voie à suivre. Cela ne vous lierra pas dans une mise en œuvre et réduira les problèmes de sécurité. P>
Également en fonction du nombre d'objets impliqués ont envisagé de renvoyer l'ensemble des produits (avec des filtres nécessaires appliqués), alors que l'utilisateur final applique des filtres avec Lambdaj ou similaire. Voir: p>
Merci. Lambdaj est une approche intéressante pour appliquer des filtres post-critères (n ° 4 ci-dessus) qui ne peuvent pas être exprimés via des filtres hibernate. Mais comme vous l'avez dit, cela ne va pas aider à trouver la méthode () due au volume de données.
Hibernate est un cadre d'infrastructure de bas niveau, et comme tel devrait rester caché dans les coulisses. Si le mois suivant, votre application doit passer à un autre cadre ORM pour une raison quelconque, votre API sera inutile. L'encapsulation entre même entre les couches dans la même application est d'une importance vitale importante. P>
Après tout cela, je pense que votre méthode devrait recevoir une abstraction des informations dont vous avez besoin pour effectuer la recherche. Je vous conseille de créer des champs énormes de Les paramètres de la méthode peuvent être une liste des restrictions d'égalité, une autre liste de restrictions relatives et bien sûr un indicateur de commande (une des valeurs ENUM plus un drapeau pour ASC / desc). P>
Ceci est juste une direction générale, j'espère avoir fait mon point clair = 8 -) p> de produits code> et d'implémenter une ou deux versions simples de restriction. p>
La séparation des couches n'est pas la même que la dépendance (ou l'absence) sur la bibliothèque tierce. Si ma candidature devait changer de couches Orm, cette API serait le dernier de mes problèmes (beaucoup plus bas sur la liste que des centaines d'entités hibernées-annotées et des milliers de requêtes HQL qui devront tous être refaites). Ce point de côté, ce que vous suggérez est mon propre ré-implémentation (plus restreint) de détachement (plus restreint) avec des noms de propriété enveloppés davantage dans Enum au cas où l'interface de mon produit doit changer le mois prochain? :-) Ou j'ai mal compris?
Combinant les résultats (appliquer plusieurs restrictions) pourrait être laissé comme quelque chose pour les clients à faire après avoir reçu le résultat défini en utilisant des collections et des prédicats. Vous pouvez même construire quelques prédicats communs pour les consommateurs de votre API juste pour être gentil. CollectionUtilsS.Select () est amusant. P> Option Deux: strong> S'il n'est pas possible d'élargir l'API, votre troisième balle est celle que j'irais avec. P> Vous pouvez essayer d'appliquer une approche de style DSL à la nommée à l'aide de quelque chose qui s'apparente au modèle de constructeur pour rendre les choses plus lisibles et naturelles. Cela obtient un peu maladroit en Java avec tous les points et parens, mais peut-être quelque chose comme: p>
Merci pour la réponse. Alors que la riche API fonctionne bien pour les clients «connus» (par exemple, d'autres services avec des requêtes prévisibles / connues), il ne fonctionnera pas pour l'interface utilisateur où les critères / ordre de tri spécifiés arbitrairement par les utilisateurs. Les requêtes de type QBE approchent rapidement des API de détachée complète de la complexité une fois que des associations / collections sont impliquées, ce n'est pas non plus la solution. Donc, le consensus semble être sur la réinventer la roue ici, hein? Je n'aime vraiment pas ça :-(
Peut-être évaluer si les clients ont besoin absolument tout. Dans des situations similaires, par exemple, je fournis les résultats aux applications consommatrices dans un ordre de tri par défaut et, s'ils veulent que les résultats triés sont triés différemment, je leur laisse la sorte d'exécuter le tri alternatif.
Je pense Query par exemple travaillerait vraiment bien ici. P>
Je ne suis pas d'accord. Hibernate Qbes sont extrêmement i> Limited - "Equals" / "Comme" uniquement, il n'y a pas de regroupement de condition, etc ... et que votre propre implémentation est effectivement la même chose que de rédiger votre propre version de détachectedcriteria
La solution réelle que j'ai implémentée utilise une approche hybride.
Méthodes utilisant des requêtes bien définies (par exemple, des méthodes utilisées en interne par d'autres services, des rapports prédéfinis, etc.) ont une signature similaire aux méthodes de Findby HibernateTemplate: p> où ou p> accès à de telles méthodes est limitée au code "fiducié"; Les requêtes utilisées doivent évidemment être définies dans les mappages hibernate. Les filtres sont intégrés à une requête ou définis comme filtres de session. Les avantages sont du code plus propre (aucun problème semblable aux critères répartis sur une demi-page) et défini clairement HQL (plus facile à optimiser et à traiter le cache si nécessaire). P> méthodes qui sont exposées à l'interface utilisateur ou sinon besoin d'être plus dynamique d'utilisation Rechercher interface de Hibernate-generic-DAO projet. C'est un peu similaire à la discriveur de Hibernate, mais présente plusieurs avantages: P> Il peut être créé sans être attaché à une entité particulière. C'est une grosse affaire pour moi car l'interface d'entité (une partie de l'API visible pour les utilisateurs) et la mise en œuvre (Pojo mappée dans Hibernate) sont deux classes et implémentation de Pojo) sont deux classes et implémentation différentes ne sont pas disponibles pour l'utilisateur à l'heure de la compilation. P> LI>
C'est une interface ouverte bien pensée; Très différente de la démonnaissance détachée à partir de laquelle il est presque impossible d'extraire quelque chose (oui, je sais que DC n'a pas été conçu pour cela; mais toujours) p> li>
Pagination intégrée / Résultats avec nombre total / bouquet d'autres petites Néties. p> li>
aucun cravatement explicite d'hibernation (bien que je ne me soucie pas vraiment de cela; je ne vais pas abandonner soudainement hibernate et aller avec Eclipselink demain); Il y a à la fois des implémentations d'hibernate et de JPA générique disponibles. P> Li>
ol> Les filtres peuvent être ajoutés à la recherche côté service; C'est lorsque la classe d'entité est également spécifiée. La seule chose qui manque est manquante à l'échec rapide du côté du client si le nom de la propriété non valide est spécifié et qui peut être résolu en écrivant ma propre implémentation d'ISEARCH / IMUTALECH, mais je n'ai pas encore reçu cela. P> P> QueryParameterers code> est une classe de commodité permettant de spécifier des paramètres nommés explicitement ou de les prendre d'un haricot. L'utilisation des échantillons est la suivante: p>
On dirait que cette question a été augmentée de deux mois; Je suis curieux de ce que tu as réglé? Je pense que j'aurais pris le n ° 3, "écrivez ma propre approche ..." a essayé de "aplatir" des informations d'informations dont j'avais besoin dans les API de ProducesVice / Critères en tant que propriétés requérantes, en fonction de l'utilisation.
@RMORRISEY - J'ai ajouté une réponse décrivant ma solution.