Jdbi: Le mappeur intégré pour ZonedDateTime supprime les informations de fuseau horaire

Créé le 21 déc. 2017  ·  43Commentaires  ·  Source: jdbi/jdbi

Il existe un mappeur intégré pour ZonedDateTime qui ressemble au TIMESTAMP WITH TIME ZONE SQL est directement pris en charge, mais le mappeur ne le fait pas.

Je pense qu'exposer un mappeur pour un type conscient de zone qui n'est pas conscient de la zone n'est pas la bonne chose à faire.

bug feature improvement

Commentaire le plus utile

Pour être honnête, je suis d'accord avec @findepi où il a dit que jdbi ne devrait pas fournir de mappeurs pour des choses qui ne peuvent pas être mappées avec précision, comme les fuseaux horaires/décalages qui ne sont pas persistants... L'idée d'un "compromis" ici semble très dangereuse pour moi - J'ai toujours considéré l'intégrité complète des données comme l'une des plus hautes priorités de tout projet. Les utilisateurs ne devraient pas avoir besoin de vérifier que les bibliothèques fonctionnent correctement.

Je préfère découvrir avec une exception d'exécution lors d'un test que jdbi ne fournit pas de mappeur pour un type donné, puis en écrire un moi-même, plutôt que de découvrir qui sait quand un mappeur fourni par jdbi a été modifié sournoisement mes données.

J'ai un grand test unitaire qui écrit puis lit des valeurs de nombreux types, pour vérifier l'exactitude de l'implémentation/l'intégrité des données à la fois dans la base de données elle-même (hsqldb) et dans jdbi, afin que je puisse écrire des mappeurs/arguments jdbi pour gérer tous les problèmes. J'ai dû en écrire plusieurs maintenant car hsqldb n'a actuellement pratiquement aucun support pour java.time malgré la spécification qui le dit (énorme bogue). Je n'avais pas encore pensé à tester les objets java.time avec des zones/offsets autres que celui de mon système, alors je viens de le faire, et bien sûr, ils reviennent tous avec l'offset/zone réinitialisé aux valeurs du système, mais en raison du mappage de jdbi à Timestamp, pas à cause de bogues hsqldb.

Je suggère que ces mappeurs défectueux soient supprimés de jdbi3 et déplacés dans des artefacts spécifiques au fournisseur (jdbi3-hsqldb et autres) où leur implémentation peut être totalement correcte.

Je pourrais peut-être contribuer moi-même à jdbi-hsqldb puisque j'ai déjà écrit tous les mappeurs et arguments nécessaires pour mon propre projet.

Tous les 43 commentaires

Vous avez raison, mais c'est tout ce que JDBC prend en charge pour le moment. Nous devons convertir tous les types java.time en types java.util ou java.sql qui manquent de données de fuseau horaire / décalage.

Par curiosité, utilisez-vous Postgres ? Parce que leur TIMESTAMP WITH TIME ZONE se comporte différemment de ce à quoi vous vous attendriez.

utilisez-vous Postgres ? Parce que leur TIMESTAMP WITH TIME ZONE se comporte différemment de ce à quoi vous vous attendriez.

je suis conscient. (Grosse déception pour une base de données par ailleurs très conforme aux normes d'ailleurs.)

Vous avez raison, mais c'est tout ce que JDBC prend en charge pour le moment.

Je m'attendais à ce que JDBI tire les org.h2.api.TimestampWithTimeZone H2 sans avoir besoin de moi pour le faire manuellement, _d'une certaine manière_.
Comme je ne connais aucun moyen "portable" (travaillant sur différents pilotes) pour extraire la valeur TIMESTAMP W/TZ, je n'ai pas de vraie solution.
Cependant, si vous ne récupérez pas toutes les informations, vous ne devriez pas prétendre le faire - c'est-à-dire IMO, il ne devrait pas y avoir de mappeur intégré à ZonedDateTime . Sinon, vous faites exactement comme Postgres - pas ce à quoi je m'attendrais.

Je pense que c'est toujours pratique si un utilisateur veut utiliser ZonedDateTime et ne se soucie pas qu'il soit renvoyé dans le fuseau horaire du serveur d'applications au lieu du fuseau horaire de la base de données.

Soit dit en passant, Dropwizard utilise une version différente du mappeur pour JDBI2, où un utilisateur peut définir explicitement le fuseau horaire de la base de données : https://github.com/dropwizard/dropwizard/blob/master/dropwizard-jdbi/src/main/java /io/dropwizard/jdbi/args/ZonedDateTimeMapper.java

Si vous pouviez fournir un exemple de code pour savoir comment obtenir/définir ZonedDateTime avec H2, je serais heureux de l'ajouter au plugin.

Je pense que c'est toujours pratique si un utilisateur souhaite utiliser ZonedDateTime et ne se soucie pas qu'il soit renvoyé dans le fuseau horaire du serveur d'applications au lieu du fuseau horaire de la base de données.

@arteam , Si l'utilisateur est conscient de faire ce choix - je suis d'accord.

Cependant, AFAIR https://github.com/jdbi/jdbi/blob/master/core/src/main/java/org/jdbi/v3/core/mapper/BuiltInMapperFactory.java#L182 ne fonctionnera même pas sur H2 pour TS w TZ, car rs.getTimestamp(..) n'est pas pris en charge pour ce type.

Si vous pouviez fournir un exemple de code pour savoir comment obtenir/définir ZonedDateTime avec H2, je serais heureux de l'ajouter au plugin.

Je ne connais aucun moyen portable - le seul moyen que je connaisse est (org.h2.api.TimestampWithTimeZone) rs.getObject(..) et pour Oracle, par exemple, ce serait similaire, mais avec une classe spécifique à Oracle.

En règle générale, je préférerais être _forcé_ par l'API pour utiliser la transformation correcte (horodatage à LocalDateTime ) et ajouter "zone-ing" explicitement.

Vous semblez être en désaccord, ce qui signifie qu'il ne sert à rien de garder cette question ouverte.

Une chose que nous faisons dans notre pile, nous affirmons en fait que le fuseau horaire de Java == le fuseau horaire de Postgres, auquel cas tout fonctionne parfaitement. Devrions-nous peut-être émettre un avertissement en cas de non-concordance ? Serait-ce un bon compromis entre activer les fonctionnalités que les gens attendent et être TZ-correct ?

Je ne sais pas pourquoi vous avez fermé cela si rapidement, je sentais qu'il y avait plus à discuter.

Même si nous ne pouvons pas résoudre ce problème de manière générique pour tous les fournisseurs, nous pouvons certainement le prendre en charge pour chaque fournisseur.

Les mappeurs et les fabriques d'arguments fournis avec Jdbi peuvent être remplacés simplement en enregistrant un autre mappeur/argument. Le dernier enregistré (par type) gagne.

Si vous regardez la source pour PostgresPlugin , vous verrez qu'elle enregistre JavaTimeMapperFactory qui fournit des mappeurs alternatifs utilisant ResultSet.getObject(Class) pour LocalDate , LocalTime , LocalDateTime et OffsetDateTime , qui sont directement pris en charge par le pilote Postgres JDBC.

Si H2 a un moyen de stocker ZonedDateTime sans supprimer la zone, nous pouvons modifier H2DatabasePlugin pour utiliser un mappeur personnalisé pour cela.

Je vais rouvrir cela pour l'instant, il y a une bonne discussion à avoir ici, et @findepi nous nous soucions beaucoup de faire les choses correctement ! Nous sommes également juste pragmatiques et les gens s'attendent à pouvoir utiliser les types de temps...

Dois-je bien comprendre de cette conversation que l'équipe jdbi serait intéressée par exemple par un sous-projet/artefact/artefact jdbi3-hsqldb qui fournit des arguments et des mappeurs spécifiquement pour hsqldb (qui prend en charge l'utilisation d'objets java.time directement via setObject/getObject sans conversion)?

Absolument.

Pour être honnête, je suis d'accord avec @findepi où il a dit que jdbi ne devrait pas fournir de mappeurs pour des choses qui ne peuvent pas être mappées avec précision, comme les fuseaux horaires/décalages qui ne sont pas persistants... L'idée d'un "compromis" ici semble très dangereuse pour moi - J'ai toujours considéré l'intégrité complète des données comme l'une des plus hautes priorités de tout projet. Les utilisateurs ne devraient pas avoir besoin de vérifier que les bibliothèques fonctionnent correctement.

Je préfère découvrir avec une exception d'exécution lors d'un test que jdbi ne fournit pas de mappeur pour un type donné, puis en écrire un moi-même, plutôt que de découvrir qui sait quand un mappeur fourni par jdbi a été modifié sournoisement mes données.

J'ai un grand test unitaire qui écrit puis lit des valeurs de nombreux types, pour vérifier l'exactitude de l'implémentation/l'intégrité des données à la fois dans la base de données elle-même (hsqldb) et dans jdbi, afin que je puisse écrire des mappeurs/arguments jdbi pour gérer tous les problèmes. J'ai dû en écrire plusieurs maintenant car hsqldb n'a actuellement pratiquement aucun support pour java.time malgré la spécification qui le dit (énorme bogue). Je n'avais pas encore pensé à tester les objets java.time avec des zones/offsets autres que celui de mon système, alors je viens de le faire, et bien sûr, ils reviennent tous avec l'offset/zone réinitialisé aux valeurs du système, mais en raison du mappage de jdbi à Timestamp, pas à cause de bogues hsqldb.

Je suggère que ces mappeurs défectueux soient supprimés de jdbi3 et déplacés dans des artefacts spécifiques au fournisseur (jdbi3-hsqldb et autres) où leur implémentation peut être totalement correcte.

Je pourrais peut-être contribuer moi-même à jdbi-hsqldb puisque j'ai déjà écrit tous les mappeurs et arguments nécessaires pour mon propre projet.

Je suis d'accord que cela aurait probablement été le chemin le plus sage, mais à ce stade, la v3 est sortie et le chat est sorti du sac.

La suppression de ces mappeurs ou fabriques d'arguments serait un changement décisif pour tous les utilisateurs existants qui en dépendent.

Si quelqu'un dépend déjà d'eux (conscient de leurs défauts ou non), je pense qu'il serait assez simple pour ces utilisateurs de les corriger : les conversions sont à peu près simples. En revanche, les garder à l'intérieur conduira à de plus en plus de personnes comme moi qui supposent que cela fonctionne parce que c'est fourni (honnêtement, qui connaît toutes les spécifications techniques comme la non-prise en charge des fuseaux horaires par jdbc ?) et peut ou non découvrir plus tard que leurs données étaient mal gérées...
Fondamentalement, je pense que les dommages potentiels futurs en leur permettant de rester sont bien plus importants que les dommages causés maintenant aux quelques-uns qui ont mis à jour en les supprimant.

@TheRealMarnes, je pense que supprimer une fonctionnalité (même une fois que nous convenons qu'elle ne devrait pas exister) n'est pas si simple. Les gens ont tendance à assumer le versioning sémantique (que le projet le suive ou non). Je ne connais pas les règles du projet, mais généralement vous le déprécierez tout au plus dans la v3 (ici la dépréciation est délicate, car il n'y a pas de méthode API qui peut être marquée comme dépréciée, la documentation et la journalisation sont ce qui reste) et supprimez la fonctionnalité dans la v4 , en s'attendant à ce que les utilisateurs lisent les notes de version / le guide de migration.

Je suis d'accord que quelque chose comme ça n'est jamais simple et que les solutions rendront toujours quelqu'un malheureux, mais j'ai tendance à penser que la fin justifie les moyens et bouleverser un système défectueux pour le remplacer par un meilleur en vaut toujours la peine à long terme. Et je ne pense pas qu'il soit déraisonnable de s'attendre à ce que les gens lisent les notes de publication / le guide de migration... Avec la maintenance et les mises à jour mineures, bien sûr, mais pas avec une mise à jour majeure. Jdbi3 lui-même est inutilisable venant de jdbi2 sans lire également le nouveau guide.

Je pense que je pourrais trouver une solution pour désactiver ces mappeurs / arguments, à condition que leur réintégration soit une simple ligne - peut-être déplacer ces mappeurs vers un plugin ?

Comme un jdbi3-core-experimental non spécifique au fournisseur ?
Edit : mon mauvais, tu veux dire jdbi.installPlugin(new ExperimentalMappersPlugin())

Ce serait l'idée, bien que ce ne soient pas vraiment «expérimentaux» en tant que tels.

TimezoneInsensibleJavaTimeMappers puis :P

Il n'y a pas que les mappeurs, ce sont aussi les usines d'arguments.

Que diriez-vous de JavaTimeYoloTZPlugin :wink:

Même si nous ne pouvons pas résoudre ce problème de manière générique pour tous les fournisseurs, nous pouvons certainement le prendre en charge pour chaque fournisseur.

@ qualidafial j'ai appris récemment qu'il semble y avoir une norme de facto émergente pour récupérer les valeurs de date/heure dans le monde post-Java8.

Tout d'abord, un peu plus de contexte :

  • J'ai créé ce problème à propos de la conversion TIMESTAMP WITH TIME ZONE JDBI en ZonedDateTime , qui supprime les informations de fuseau horaire
  • il y a un autre problème, avec toutes les API JDBC. C'est ainsi que les objets TIMESTAMP , DATE , TIME sont censés être récupérés, c'est-à-dire en utilisant les classes java.sql.{Timestamp,Date,Time} . Les cours s'étendent tous à partir de java.util.Date . Quelqu'un se souvient comment Calendar été introduit et les méthodes de java.util.Date traitant de l'année/mois/jour/heure/minute/seconde étaient dépréciées ? Pour une bonne raison (et je ne veux pas dire que Calendar résolu tous les problèmes).

    • vous ne pouvez pas récupérer java.sql.Timestamp partir d'une base de données, si votre _fuseau horaire JVM_ n'a pas observé une telle heure locale. Ainsi, une application exécutée aux États-Unis peut stocker une valeur d'horodatage de 2017-03-26 02:30:00 (sans zone !) dans une base de données partagée, mais une application exécutée en Europe (avec par exemple Europe/Berlin comme zone JVM) ne le fera pas pouvoir récupérer cet horodatage, car il y avait l'heure d'été en Europe à cette époque.

    • oh, la même chose s'applique à java.sql.Date , car c'est une classe presque identique. java.sql.Date représente la date comme si c'était java.sql.Timestamp à minuit, mais parfois il n'y a pas minuit. Il existe des zones avec des changements d'heure d'été à minuit (actuels ou passés).

    • pensez-vous que java.sql.Time est exempt de ce problème, car il représente l'heure récupérée sous forme d'horodatage le 1970-01-01 ? Malheureusement non, car il y a des zones qui ont été assez bien pour avoir un changement de politique à cette date (par exemple America/Bahia_Banderas , America/Hermosillo ). Si JVM fait partie de ces zones, un programme utilisant JDBC ne pourra pas récupérer certaines valeurs TIME .

Une non-solution serait de récupérer à l'aide de l'ancienne API JDBC et de les convertir en nouvelles classes. Mais c'est généralement faux :

  • ~ resultSet.getTimestamp(col).toLocalDateTime() ~
  • ~ resultSet.getDate(col).toLocalDate() ~
  • ~ resultSet.getTime(col).toLocalTime() ~

Cela compile et fonctionne bien, sauf que cela ne résout aucun des problèmes décrits ci-dessus (même la récupération de la date ne fonctionne pas, si la zone JVM est Pacific/Apia et la date récupérée est 2011-12-30 ;)

Maintenant, à la solution émergente. ResultSet possède cette API moins populaire vous permettant de demander au pilote JDBC de convertir le type pour vous :

  • resultSet.getObject(col, LocalDateTime.class) // for TIMESTAMP
  • resultSet.getObject(col, LocalDate.class) // for DATE
  • resultSet.getObject(col, LocalTime.class) // for TIME
  • resultSet.getObject(col, ZonedDateTime.class) // for TIMESTAMP WITH TIME ZONE

Cela semble fonctionner avec les pilotes JDBC pour PostgreSQL, MySQL, Oracle et H2. Et, par magie, contourne les problèmes de « non-représentabilité en zone JVM » décrits ci-dessus.
Même si cette conversion n'est pas encore implémentée dans, par exemple, le pilote SQL Server, je pense que cela pourrait être le mappage par défaut pour les classes Java Time livrées par JDBI.

Noter:
La spécification JDBC 4.2 n'exige pas qu'un pilote doive l'implémenter. Cependant, la spécification exige que PreparedStatement.setObject et RowSet.setObject acceptent les instances des classes Java Time et les traitent correctement, les pilotes doivent donc de toute façon prendre en charge ces classes explicitement.

C'est super! Ma principale préoccupation est que le passage à cette approche pourrait se manifester par une régression pour les utilisateurs utilisant des pilotes ésotériques. Mais peut-être qu'avec des messages appropriés sur les notes de version, nous pourrions apporter ce petit changement techniquement révolutionnaire au nom de faire les choses de la bonne manière...

@stevenschlansker tu as raison. Je pense que JDBI pourrait fournir

  • ensemble facultatif de mappages qu'un utilisateur peut brancher pour restaurer le comportement d'origine
  • quelques commentaires appropriés dans les notes de version (ou même une version majeure)

Restons-en à une version mineure, nous venons de sortir 3, et ce n'est qu'un changement décisif si vous vous trompez... ;)

Juste pour écouter ce que j'ai l'impression d'entendre :

  • Déplacez les mappeurs java.time intégrés existants dans un plugin séparé (j'aime YoloTimePlugin )
  • Ajoutez à leur place de nouveaux mappeurs intégrés qui utilisent ResultSet.getObject(column, type) au lieu de convertir à partir des types java.sql.
  • Documentez la merde de ce changement de rupture dans les notes de version : expliquez l'impact de ce changement et quels fournisseurs de bases de données seront touchés, et ce que les utilisateurs doivent faire pour atténuer les problèmes

Je peux supporter cette idée.

Cependant, nous n'avons toujours pas répondu à la question sur la liaison de ces objets date/heure. Tout ce que nous modifions concernant le mappage des résultats _hors_ de la base de données doit être mis en miroir dans la manière dont nous lions les arguments date/heure _dans_ les instructions SQL.

Tout ce que nous changeons concernant le mappage des résultats hors de la base de données doit être reflété dans la manière dont nous lions les arguments date/heure dans les instructions SQL.
@qualidafial , très bonne question. Je n'ai pas testé ça. Ceci est explicitement couvert par la spécification JDBC 4.2, donc _devrait simplement fonctionner™_.

Ceci est explicitement couvert par la spécification JDBC 4.2, donc _devrait simplement fonctionner™_.

Cela suppose que les implémenteurs de pilotes JDBC suivent parfaitement les spécifications. Je n'ai pas encore trouvé d'implémentation de pilote JDBC sans bogues.

J'ai l'impression qu'il serait trop lourd de fournir des plugins avec des mappeurs pour chaque base de données et même ses différentes versions qui prennent en charge différents types de données. Peut-être qu'une approche plus vierge pourrait fonctionner : vous commencez avec une instance Jdbi sans mappeurs préinstallés, et l'artefact de base fournit un tas de mappeurs différents que vous pouvez choisir manuellement pour installer, certains ayant une logique différente pour gérer les mêmes types de données - get/ setObject, get/setX, conversion vers un autre type, etc. Vous devrez déterminer par vous-même quels mappeurs conviennent le mieux à votre base de données (version) et à la logique de votre application, et utiliser des tests unitaires pour les contrôler.

C'est en gros ce que je fais déjà maintenant de toute façon dans mon projet. Il y a des mappeurs préinstallés dans Jdbi qui ne fonctionnent pas avec ma base de données et je n'en ai pas besoin pour le moment, donc je les ai remplacés avec des usines d'arguments/mapper qui lancent une UnsupportedOperationException, et d'autres avec lesquels j'ai remplacé mieux réalisations (voir ci-dessous).

Ce serait une solution pour ceux qui aiment se familiariser avec leur base de données pour s'assurer que tout fonctionne parfaitement, et ne changerait rien pour les personnes qui veulent des trucs sur Just Werk™ (dans la mesure où c'est réellement le cas) :

  • ajouter une méthode aux instances Jdbi pour effacer tous leurs mappeurs/arguments (tableau propre)
  • exposer les impls mapper/arg intégrés actuels pour que nous les installions manuellement
  • continuez à ajouter d'autres outils de mappage à l'artefact de base lorsque la demande augmente et laissez les gens les installer eux-mêmes, en générant tout ce qui est possible comme ci-dessous

En faisant cela, j'ai réussi à trouver... beaucoup trop de points dans le pilote hsqldb où ils s'écartent de leurs propres spécifications (rapportés et corrigés dans la source, attendant toujours qu'ils publient enfin un artefact mis à jour), et ont travaillé contourner ces imperfections en trouvant moi-même la logique de mappage de travail.

// I want strings handled differently
<strong i="13">@Component</strong>
public class CleanStringArgumentFactory extends AbstractArgumentFactory<String> {
    protected CleanStringArgumentFactory() {
        super(Types.VARCHAR);
    }

    <strong i="14">@Override</strong>
    protected Argument build(String value, ConfigRegistry config) {
        return (position, statement, ctx) -> statement.setString(position, StringUtils.trimToNull(value));
    }
}
// no need for jdbi's built-in logic
<strong i="17">@Component</strong>
public class SetObjectArgumentFactory implements ArgumentFactory {
    private static final Set<Type> SUPPORTED = ImmutableSet.of(UUID.class, LocalDateTime.class);

    <strong i="18">@Override</strong>
    public Optional<Argument> build(Type type, Object value, ConfigRegistry config) {
        return SUPPORTED.contains(type)
            ? Optional.of(new LoggableArgument(value, (position, statement, context) -> statement.setObject(position, value)))
            : Optional.empty();
    }
}
// these built-ins don't work and I don't need them anyway
<strong i="21">@Component</strong>
public class UnsupportedArgumentFactory implements ArgumentFactory {
    private static final Set<Type> UNSUPPORTED = ImmutableSet.of(ZonedDateTime.class, OffsetDateTime.class, OffsetTime.class);

    <strong i="22">@Override</strong>
    public Optional<Argument> build(Type type, Object value, ConfigRegistry config) {
        if (UNSUPPORTED.contains(type)) {
            throw new UnsupportedOperationException(type.getTypeName() + " is not supported at the moment");
        } else {
            return Optional.empty();
        }
    }
}
// voodoo
<strong i="25">@Inject</strong>
    public JdbiConfiguration(
        @Named("dataSource") DataSource dataSource,
        Set<ArgumentFactory> arguments,
        Set<ColumnMapper> mappers,
        Set<ColumnMapperFactory> mapperFactories
    ) {
        jdbi = Jdbi.create(dataSource);
        jdbi.clearMappings();

        jdbi.installPlugin(new SqlObjectPlugin());

        arguments.forEach(jdbi::registerArgument);
        mapperFactories.forEach(jdbi::registerColumnMapper);
        mappers.forEach(jdbi::registerColumnMapper);

        // ...

        // Jdbi instance fine-tuned for my exact database and demands, without surprises and at my own responsibility

Howbouda ? Vous pouvez par exemple fournir un SetObjectArgumentFactory qui doit être initialisé avec un ensemble de classes sur lesquelles il doit s'activer, et toutes sortes de variations de logique de mappage pour de nombreux types de données, avec un comportement configurable le cas échéant. Tout le monde heureux. Cela demande un peu de travail à l'utilisateur final, mais je me sens bien de savoir que jdbi fait exactement ce que je veux qu'il fasse et ce que ma base de données prend en charge.

J'ai l'impression qu'il serait trop lourd de fournir des plugins avec des mappeurs pour chaque base de données et même ses différentes versions qui prennent en charge différents types de données.

J'aimerais avoir des plugins pour de nombreux fournisseurs de bases de données. Venez, venez tous : si votre base de données a besoin/veux de personnalisations pour adapter Jdbi aux particularités du fournisseur de la base de données ou de son pilote JDBC, nous voulons en entendre parler. Ou mieux encore, nous voulons des demandes de tirage ! :)

Points bonus si votre base de données est prise en charge directement par TravisCI afin que nous puissions réellement effectuer des tests sur celle-ci : https://docs.travis-ci.com/user/database-setup/

Quant à votre suggestion de "tableau vierge", je n'ai que des objections mineures :

  • Je mettrais probablement la méthode clearMappings() directement sur les classes de configuration RowMappers , ColumnMappers , Arguments et JdbiCollectors au lieu de Jdbi , et je les nommerais clear() .
  • J'hésite un peu à rendre publics les mappeurs, arguments et collectionneurs intégrés. Certains d'entre eux ont des noms ou des conceptions bancales avec lesquelles nous nous en sortons parce qu'ils sont internes. Je voudrais probablement les refactoriser avant de les intégrer à l'API.
  • Je me demande si l'ardoise vierge est vraiment nécessaire. Toutes les classes de registre de Jdbi utilisent l'approche des derniers enregistrements enregistrés, il est donc toujours possible de remplacer le comportement prêt à l'emploi. En ce sens, l'ardoise vierge semble un peu exagérée.

@jdbi/contributors, quelqu'un d'autre veut-il peser ?

J'ai inclus l'idée de l'ardoise vierge pour éviter d'utiliser accidentellement un mappeur par défaut au cas où vous oublieriez d'enregistrer l'un de votre choix. Je préfère avoir une NotImplementedException qu'une impl par défaut. Les derniers gains, c'est bien, mais il n'y a aucun moyen de savoir lesquels vous devez annuler au cas où vous n'en voudriez pas.

Ce n'est pas comme si ça faisait mal d'avoir. Si les gens ne veulent pas de cette approche, ils n'ont pas besoin d'appeler les méthodes claires et rien ne change pour eux. C'est juste pour ceux qui préfèrent une méthode de travail sans défaut.

Je suis d'accord pour dire que nous ne devrions pas simplement rendre publics les cartographes existants. Si nous choisissons de fournir une option de table rase, nous devons regrouper les mappeurs et les classeurs en morceaux raisonnables Plugin , PrimitivesPlugin , BoxedPrimitivesPlugin , CollectionsPlugin , peu importe.

Ensuite, nous pouvons ajouter une nouvelle usine pour le jdbi "de base" sans aucune configuration, et modifier les usines existantes pour l'utiliser et ajouter le WholeJdbiEnchiladaPlugin .

Je suis un peu contre 'clear' à moins que nous puissions montrer des cas où il est difficile de le construire de manière additive - cela me semble une odeur de code.

Je suis un peu contre 'clear' à moins que nous puissions montrer des cas où il est difficile de le construire de manière additive - cela me semble une odeur de code.

Eh bien, si vous ajoutez une fabrique jdbi distincte sans préconfiguration, il ne sera pas difficile de la construire de manière additive, nous n'aurons donc pas besoin de clear().

Bon, je pense que nous sommes d'accord ici, j'exprimais juste une préférence pour l'ajout d'une nouvelle méthode d'usine "propre" par rapport à un style clear() .

Alors, est-ce que cela résout les problèmes de tout le monde alors ? Personnellement, je pense que le plan semble assez sexy.

  • make Jdbi no-defaults (lance des exceptions sur à peu près tout)
  • rendre tous les mappeurs et classeurs existants (et les gestionnaires tx, etc.) enfichables ( PrimitivesPlugin , BoxedPrimitivesPlugin , etc.), en tant que bundles de plugins et classes individuelles
  • fournir des implémentations alternatives ( UTCJavaTimePlugin vs LocalJavaTimePlugin vs ConvertJavaTimeToUtilDatePlugin , GetObjectMapper.forClasses(Class... cs) , SetObjectArgumentFactory.forClasses(Class... cs) , NullsToDefaultsPrimitivesPlugin vs NullThrowsExceptionPrimitivesPlugin ) et les exposer de la même manière (dans les plugins et individuellement), afin que les utilisateurs puissent composer leur propre logique de mappage totale souhaitée, en ne prenant exactement que ce qu'ils veulent. Potentiellement beaucoup de configuration de mappeur nécessaire ici, comme différentes stratégies pour gérer les valeurs nulles illégales ou les fuseaux horaires manquants, et d'autres disparités possibles
  • peut-être créer des plugins de bundle spécifiques à la base de données, afin que les utilisateurs avec des bases de données + versions populaires puissent commencer à partir d'un Jdbi sans configuration et installer en une ligne de bons schémas de mappage connus pour leur base de données ( HsqlDb2_4_0Plugin ), encore une fois avec des options de configuration pour différentes stratégies
  • et rendre le tout rétrocompatible en faisant simplement en sorte que les méthodes d'usine actuelles effectuent la préconfiguration que nous avons actuellement ( BuiltInGenericPreconfigurationPlugin ), aux côtés des méthodes d'usine sans configuration.

faire Jdbi pas de valeurs par défaut

Je n'ai pas d'opinion très tranchée, mais tout cela semble très complexe du point de vue de l'utilisateur. Les utilisateurs devront comprendre les différents mappages possibles pour les types qu'ils souhaitent utiliser et en choisir un approprié. C'est difficile, surtout lorsque les temporels sont en jeu - ce n'est vraiment pas anodin de comprendre les différentes options possibles.

Les utilisateurs devront comprendre les différents mappages possibles pour les types qu'ils souhaitent utiliser et en choisir un approprié

Non, seulement s'ils le souhaitent. Les méthodes d'usine existantes continueront à produire des instances de Jdbi avec exactement les mêmes mappeurs préinstallés qu'elles le font maintenant. Nous aurons juste en plus des méthodes d'usine de configuration de bricolage, et les personnes qui optent pour celles-ci devront comprendre les intimités de la cartographie. Il y aura aussi un chemin intermédiaire, où vous obtiendrez une instance de bricolage et installez simplement le YourDbAndVersionPlugin et roulez avec tout ce qu'il fait. Ma longue explication concernait principalement les composants internes de jdbi et l'utilisation avancée, pas la ligne de base.

TLDR : Vous pourrez toujours faire Jdbi.create(dataSource) et vous n'aurez pas besoin de vous en dire plus que vous ne le faites déjà. Quelqu'un d'autre choisira simplement de Jdbi.createBlank(dataSource).install(x).install(y).install(z)...

Je suis d'accord, sauf que je ne pense pas que nous devrions déprécier les usines existantes, je pense que la plupart des utilisateurs continueront à l'utiliser car le comportement "prêt à l'emploi" est plutôt bon.

Assez juste

@TheRealMarnes Toute cette conversation a commencé sur les types de données JSR-310 qui ne sont pas pris en charge directement par JDBC.

Je pense qu'il existe un consensus sur la suppression des mappeurs et des arguments java.time errants et de les mettre dans un plugin au lieu de les intégrer.

Voulez-vous toujours poursuivre cela?

Juste les java.time ? Un JavaTimePlugin ?

Oui, un plugin uniquement pour les types java.time, mais nommé pour communiquer que les arguments et les mappeurs sont des implémentations naïves et avec perte comme @findepi l'a décrit.

SimplisticJavaTimePlugin ?

Attendre avec ça que mes autres PR soient pris en charge... C'est un peu trop en même temps.

Cette page vous a été utile?
0 / 5 - 0 notes