2010-12-06 41 views
2

Donc je travaille sur un projet (JSF2, Spring3 Core, MVC, Webflow, MyBatis3, RichFaces, et un héritage 10g Oracle). La source de tous mes problèmes a à voir avec la conception de la base de données. Le problème est que la majorité des tables de DB ont un schéma changeant (mauvaise conception peut-être?). Donc, je dois être en mesure de soutenir l'ajout & suppression des colonnes supplémentaires. Pour cela, j'ai fait en sorte que MyBatis tisse des données dans un objet de domaine "universel" personnalisé qui ne fait que prolonger un hashmap. Mon problème actuel est la mise à jour de ces objets hashmap. Il devrait y avoir un moyen de le faire fonctionner, mais je peux sembler obtenir que MyBatis coopère. J'ai essayé d'utiliser HashMap.entrySet() & MyBatis, mais en vain. par exemple.Besoin d'aide pour faire fonctionner MyBatis avec une conception de base de données terrible

UPDATE MYTABLE 
SET 
<foreach collection="entries" index="i" item="entry" close="" open="" separator=", "> 
    #{entry.key} = #{entry.value} 
</foreach> 
WHERE FOO='BAR'; 

J'ai essayé TypeHandler personnalisé mais setParameter() ne me donne pas un accès suffisant pour faire ce que je dois. Un ResultHandler ne m'a pas donné assez d'accès à chaque résultat individuel, donc je ne pouvais pas l'utiliser non plus.

Maintenant je sais que je pourrais faire quelque chose comme Obj.createUpdateSqlString() et l'insérer dans le mappeur sous la forme d'une chaîne littérale, mais c'est un peu un hack et me laisse ouvert à l'injection SQL. Sans compter que cela impliquerait d'échapper à beaucoup de chaînes, et de prendre en compte un large éventail d'entrées possibles, et à moins que toutes les possibilités ne soient couvertes, cela ouvre la porte à de sérieux bogues.

Alors, existe-t-il une façon établie de le faire? Ou au moins un moyen décent à mi-chemin? J'ai entendu un certain nombre de défenseurs inconditionnels de MyBatis dire qu'ils n'ont pas encore rencontré une situation que MyBatis ne pouvait pas gérer avec élégance; alors experts MyBatis, s'il vous plaît aidez-moi !! MyBatis ou Hibernate pue tous les deux avec des schémas de base de données fous.

Répondre

1

Il semble qu'ils essayaient d'éviter d'utiliser des tables EAV.

Vous devez choisir votre poison quand il s'agit d'ajouter dynamiquement des champs. EAV est bon d'un point de vue théorique, mais a de sérieux problèmes de performance sur les grandes tables. Alors que l'ajout dynamique de colonnes est préférable pour les performances de requête, vous devez gérer une interface de table évolutive et un SQL dynamique. Je ne voudrais pas écrire la base de données comme une mauvaise conception pure et simple.

Vous pouvez ignorer le framework que vous utilisez. Interrogez votre schéma de table (pour Oracle, consultez USER_TAB_COLUMNS) et générez les scripts d'insertion/mise à jour. Paramétrez-les pour éviter toute injection. Ce sera un mal de tête mais je ne vois pas d'alternative.

+0

Merci pour la perspicacité. J'avais l'impression que le schéma des variables était toujours une mauvaise chose, mais malgré tout, il y a beaucoup d'autres raisons pour lesquelles cette base de données a gagné sa réputation d'être mal conçue. Je suppose que je devrai juste éviter d'utiliser les mappeurs intégrés au lieu de le pirater. Paramétrer les requêtes était ma principale préoccupation, mais après avoir regardé cela, je pense que je pourrais être en mesure d'utiliser MyBatis pour cette partie au moins. Merci encore! – Stoney

+0

En général, il devrait être évité. Si des colonnes sont ajoutées au moment de l'exécution, cela signifie que l'utilisateur final conçoit des tables et peut enfreindre les règles de normalisation. Mais si votre application "a besoin" d'ajouter des champs à l'exécution, vous devez faire quelque chose ... et que quelque chose se résume à EAV, placer des colonnes de support, ou ajouter dynamiquement des colonnes. – mike

+0

l'une des raisons pour lesquelles la base de données peut avoir une «réputation d'être mal conçue» est que l'utilisateur final est le concepteur. L'utilisateur final peut commencer à ajouter des colonnes comme Phone1, phone2, ... phone322. Laisser l'utilisateur concevoir les tables en fait le concepteur. Votre application d'utilisateur final commence à devenir un outil de développement comme SQLDeveloper. – mike

3

Je voudrais juste utiliser SpringJDBC ou similaire. N'essayez pas de faire une cheville ronde dans un trou carré, même si c'est une très belle cheville ronde.

+0

Je suis arrivé récemment à la même conclusion, mais malheureusement MyBatis a été spécié pour ce projet au début et maintenant nous ne pouvons pas le changer (ou l'une des autres bibliothèques) pour une raison absurde. N'aimez pas les bureaucraties d'entreprise. – Stoney

+0

@Stoney, 'ne peut pas changer' est généralement juste une fonction de coût - si vous pouvez réellement prouver aux bonnes oreilles que prendre en compte tous les coûts (* toutes * les dépendances internes et externes), vous atteindriez des objectifs à moindre coûté vous seriez surpris de ce qui peut changer. D'un autre côté, si actuellement il est vraiment plus cher de changer, vous devrez le sortir (d'un autre côté, si par bureaucratique, vous choisissez de ne pas le faire parce qu'une telle analyse des coûts vous mettrait dans une mauvaise position en raison de hiérarchie, eh bien ... alors je ne vous dis rien de nouveau, alors ignorez le commentaire entier) – Unreason

+0

Il y a un moyen de le changer, dépend juste comment dur vous êtes prêt à se battre :) – bwawok