Jdbi: Pemeta bawaan untuk ZonedDateTime membuang informasi zona waktu

Dibuat pada 21 Des 2017  ·  43Komentar  ·  Sumber: jdbi/jdbi

Ada mapper bawaan untuk ZonedDateTime yang terlihat seperti SQL TIMESTAMP WITH TIME ZONE didukung secara langsung, tetapi mapper tidak melakukannya.

Saya pikir mengekspos mapper untuk tipe sadar zona yang tidak sadar zona bukanlah hal yang benar untuk dilakukan.

bug feature improvement

Komentar yang paling membantu

Sejujurnya saya setuju dengan @findepi di mana dia mengatakan bahwa jdbi tidak boleh menyediakan pembuat peta untuk hal-hal yang sebenarnya tidak dapat dipetakan secara akurat, seperti zona waktu/offset yang tidak bertahan... Gagasan "kompromi" di sini terdengar sangat berbahaya bagi saya - Saya selalu menganggap integritas data penuh sebagai salah satu prioritas tertinggi dalam proyek apa pun. Pengguna tidak perlu memeriksa ulang apakah perpustakaan berfungsi dengan benar.

Saya lebih suka mencari tahu dengan pengecualian runtime selama uji coba bahwa jdbi tidak menyediakan mapper untuk jenis tertentu dan kemudian menulis sendiri, daripada mencari tahu siapa-tahu-kapan bahwa mapper yang disediakan oleh jdbi telah diam-diam mengubah data saya.

Saya memiliki unit test besar yang menulis dan kemudian membaca nilai dari banyak jenis, untuk memverifikasi kebenaran implementasi/integritas data di db itu sendiri (hsqldb) dan jdbi, jadi saya bisa menulis jdbi mappers/argumen untuk menangani masalah apa pun. Saya harus menulis beberapa sekarang karena hsqldb saat ini pada dasarnya tidak memiliki dukungan untuk Java.time meskipun spesifikasi mengatakan demikian (bug besar). Saya belum berpikir untuk menguji objek Java.time dengan zona/offset selain dari sistem saya, jadi saya baru saja melakukannya, dan tentu saja, mereka semua kembali dengan offset/zona reset ke nilai sistem, tetapi karena pemetaan jdbi ke Timestamp, bukan karena bug hsqldb.

Saya menyarankan pembuat peta yang cacat itu dihapus dari jdbi3 dan dipindahkan ke artefak khusus vendor (jdbi3-hsqldb dan lainnya) di mana implementasinya dapat dibuat sepenuhnya benar.

Saya mungkin dapat berkontribusi jdbi-hsqldb sendiri karena saya sudah menulis semua pembuat peta dan argumen yang diperlukan untuk proyek saya sendiri.

Semua 43 komentar

Anda benar, tetapi hanya ini yang didukung JDBC saat ini. Kita harus mengonversi semua tipe java.time ke tipe java.util atau java.sql yang tidak memiliki data zona waktu/offset.

Karena penasaran, apakah Anda menggunakan Postgres? Karena TIMESTAMP WITH TIME ZONE mereka berperilaku berbeda dari yang Anda harapkan.

apakah Anda menggunakan Postgres? Karena TIMESTAMP WITH TIME ZONE mereka berperilaku berbeda dari yang Anda harapkan.

saya sadar. (Kekecewaan besar untuk database yang sangat sesuai standar btw.)

Anda benar, tetapi hanya ini yang didukung JDBC saat ini.

Saya mengharapkan JDBI untuk menarik org.h2.api.TimestampWithTimeZone H2 tanpa perlu saya melakukan ini secara manual, _somehow_.
Karena saya tidak tahu cara "portabel" (bekerja di berbagai driver) untuk menarik nilai TIMESTAMP W/TZ, saya tidak punya solusi yang benar.
Namun, jika Anda tidak menarik semua informasi, Anda tidak boleh berpura-pura melakukannya -- yaitu IMO seharusnya tidak ada mapper bawaan untuk ZonedDateTime . Kalau tidak, Anda melakukan seperti Postgres - bukan yang saya harapkan.

Saya pikir itu masih nyaman jika pengguna ingin menggunakan ZonedDateTime dan tidak peduli bahwa itu dikembalikan di zona waktu server aplikasi alih-alih zona waktu database.

Omong-omong, Dropwizard menggunakan versi mapper yang berbeda untuk JDBI2, di mana pengguna dapat secara eksplisit mengatur zona waktu database: https://github.com/dropwizard/dropwizard/blob/master/dropwizard-jdbi/src/main/java /io/dropwizard/jdbi/args/ZonedDateTimeMapper.java

Jika Anda dapat memberikan contoh kode cara mendapatkan/mengatur ZonedDateTime dengan H2, saya akan dengan senang hati menambahkannya ke plugin.

Saya pikir masih nyaman jika pengguna ingin menggunakan ZonedDateTime dan tidak peduli bahwa itu dikembalikan di zona waktu server aplikasi alih-alih zona waktu database.

@arteam , Jika pengguna sadar membuat pilihan ini - saya setuju.

Namun, AFAIR https://github.com/jdbi/jdbi/blob/master/core/src/main/Java/org/jdbi/v3/core/mapper/BuiltInMapperFactory.java#L182 bahkan tidak akan berfungsi pada H2 untuk TS w TZ, karena rs.getTimestamp(..) tidak didukung untuk jenis itu.

Jika Anda dapat memberikan contoh kode cara mendapatkan/mengatur ZonedDateTime dengan H2, saya akan dengan senang hati menambahkannya ke plugin.

Saya tidak tahu cara portabel - satu-satunya cara yang saya tahu adalah (org.h2.api.TimestampWithTimeZone) rs.getObject(..) dan misalnya Oracle akan serupa, tetapi dengan kelas khusus Oracle.

Secara umum, saya lebih suka _dipaksa_ oleh API untuk menggunakan transformasi yang benar (cap waktu ke LocalDateTime ) dan menambahkan "zona-ing" secara eksplisit.

Anda tampaknya tidak setuju, yang berarti, tidak ada gunanya membiarkan masalah ini tetap terbuka.

Satu hal yang kami lakukan di tumpukan kami, kami benar-benar menegaskan bahwa zona waktu Java == zona waktu Postgres, dalam hal ini semuanya berfungsi dengan baik. Haruskah kita mungkin mengeluarkan peringatan jika ada ketidakcocokan? Apakah itu kompromi yang baik antara mengaktifkan fitur yang diharapkan orang, dan menjadi benar TZ?

Tidak yakin mengapa Anda menutup ini begitu cepat, saya merasa ada lebih banyak untuk didiskusikan.

Bahkan jika kami tidak dapat menyelesaikan ini secara umum untuk semua vendor, kami pasti dapat mendukung ini berdasarkan per-vendor.

Pemetaan dan pabrik argumen yang dikirimkan dengan Jdbi dapat diganti hanya dengan mendaftarkan pembuat peta/argumen lain. Terakhir terdaftar (per jenis) menang.

Jika Anda melihat sumber untuk PostgresPlugin , Anda akan melihat bahwa ia mendaftarkan JavaTimeMapperFactory yang menyediakan pembuat peta alternatif menggunakan ResultSet.getObject(Class) untuk LocalDate , LocalTime , LocalDateTime dan OffsetDateTime , yang secara langsung didukung oleh driver Postgres JDBC.

Jika H2 memiliki cara untuk menyimpan ZonedDateTime tanpa menghilangkan zona, kita dapat memodifikasi H2DatabasePlugin untuk menggunakan custom mapper untuk itu.

Saya akan membukanya kembali untuk saat ini, ada diskusi bagus yang bisa dilakukan di sini, dan @findepi kami sangat peduli untuk melakukan sesuatu dengan benar! Kami juga hanya pragmatis dan orang berharap untuk benar-benar dapat menggunakan jenis waktu...

Apakah saya memahami dengan benar dari obrolan ini bahwa tim jdbi akan tertarik untuk memiliki, misalnya, subproyek/artefak/... jdbi3-hsqldb yang menyediakan argumen dan pemetaan khusus untuk hsqldb (yang mendukung penggunaan objek Java.time secara langsung melalui setObject/getObject tanpa konversi)?

Sangat.

Sejujurnya saya setuju dengan @findepi di mana dia mengatakan bahwa jdbi tidak boleh menyediakan pembuat peta untuk hal-hal yang sebenarnya tidak dapat dipetakan secara akurat, seperti zona waktu/offset yang tidak bertahan... Gagasan "kompromi" di sini terdengar sangat berbahaya bagi saya - Saya selalu menganggap integritas data penuh sebagai salah satu prioritas tertinggi dalam proyek apa pun. Pengguna tidak perlu memeriksa ulang apakah perpustakaan berfungsi dengan benar.

Saya lebih suka mencari tahu dengan pengecualian runtime selama uji coba bahwa jdbi tidak menyediakan mapper untuk jenis tertentu dan kemudian menulis sendiri, daripada mencari tahu siapa-tahu-kapan bahwa mapper yang disediakan oleh jdbi telah diam-diam mengubah data saya.

Saya memiliki unit test besar yang menulis dan kemudian membaca nilai dari banyak jenis, untuk memverifikasi kebenaran implementasi/integritas data di db itu sendiri (hsqldb) dan jdbi, jadi saya bisa menulis jdbi mappers/argumen untuk menangani masalah apa pun. Saya harus menulis beberapa sekarang karena hsqldb saat ini pada dasarnya tidak memiliki dukungan untuk Java.time meskipun spesifikasi mengatakan demikian (bug besar). Saya belum berpikir untuk menguji objek Java.time dengan zona/offset selain dari sistem saya, jadi saya baru saja melakukannya, dan tentu saja, mereka semua kembali dengan offset/zona reset ke nilai sistem, tetapi karena pemetaan jdbi ke Timestamp, bukan karena bug hsqldb.

Saya menyarankan pembuat peta yang cacat itu dihapus dari jdbi3 dan dipindahkan ke artefak khusus vendor (jdbi3-hsqldb dan lainnya) di mana implementasinya dapat dibuat sepenuhnya benar.

Saya mungkin dapat berkontribusi jdbi-hsqldb sendiri karena saya sudah menulis semua pembuat peta dan argumen yang diperlukan untuk proyek saya sendiri.

Saya setuju bahwa mungkin akan menjadi jalan yang lebih bijaksana, namun pada titik ini v3 dilepaskan dan kucing keluar dari kantong.

Menghapus pembuat peta atau pabrik argumen ini akan menjadi perubahan besar bagi pengguna yang ada yang bergantung padanya.

Jika seseorang sudah bergantung pada mereka (sadar akan kekurangan mereka atau tidak), saya pikir itu akan cukup sederhana bagi para pengguna untuk menambalnya kembali: konversinya cukup banyak satu baris. Menyimpan mereka di sisi lain akan menyebabkan semakin banyak orang seperti saya yang menganggapnya berfungsi karena disediakan (jujur, siapa yang tahu semua spesifikasi teknis seperti jdbc yang tidak mendukung zona waktu?) dan mungkin atau mungkin tidak cari tahu nanti bahwa data mereka salah ditangani...
Pada dasarnya saya pikir potensi kerusakan di masa depan dengan membiarkan mereka tetap tinggal jauh lebih besar daripada kerusakan yang ditimbulkan sekarang pada beberapa orang yang telah memperbarui dengan menghapusnya.

@TheRealMarnes saya pikir menghapus fitur (bahkan setelah kami setuju itu tidak boleh ada) tidak sesederhana itu. Orang cenderung menganggap versi semantik (terlepas dari apakah proyek mengikutinya atau tidak). Saya tidak tahu aturan proyek, tetapi biasanya Anda paling banyak akan mencelanya di v3 (di sini penghentian itu rumit, karena tidak ada metode API yang dapat ditandai tidak digunakan lagi, dokumentasi dan pencatatan adalah yang tersisa) dan hapus fitur di v4 , mengharapkan orang untuk membaca catatan rilis/panduan migrasi.

Saya setuju hal seperti itu tidak pernah sederhana dan solusi akan selalu membuat seseorang tidak bahagia, tetapi saya cenderung berpikir bahwa tujuan membenarkan cara dan mengacaukan sistem yang cacat untuk menggantikannya dengan yang lebih baik dalam jangka panjang selalu sepadan dengan kekecewaan. Dan saya tidak berpikir mengharapkan orang untuk membaca catatan rilis / panduan migrasi tidak masuk akal... Dengan pemeliharaan dan pembaruan kecil, tentu saja, tetapi tidak dengan pembaruan besar. Jdbi3 sendiri tidak dapat digunakan berasal dari jdbi2 tanpa membaca panduan baru juga.

Saya pikir saya bisa mendapatkan solusi untuk menonaktifkan pembuat peta/argumen itu, asalkan mengembalikannya adalah satu baris - mungkin memindahkan pembuat peta itu ke sebuah plugin?

Suka jdbi3-core-experimental khusus non-vendor?
Sunting: salahku, maksudmu jdbi.installPlugin(new ExperimentalMappersPlugin())

Itu idenya, meskipun ini tidak benar-benar 'eksperimental' seperti itu.

TimezoneInsensitiveJavaTimeMappers lalu :P

Bukan hanya pembuat peta, itu juga pabrik argumen.

Bagaimana dengan JavaTimeYoloTZPlugin :wink:

Bahkan jika kami tidak dapat menyelesaikan ini secara umum untuk semua vendor, kami pasti dapat mendukung ini berdasarkan per-vendor.

@qualidafial saya baru-baru ini mengetahui bahwa tampaknya ada standar de-facto yang muncul untuk mengambil nilai tanggal/waktu di dunia pasca-Java8.

Pertama, sedikit lebih banyak latar belakang:

  • saya membuat masalah ini tentang konversi TIMESTAMP WITH TIME ZONE JDBI menjadi ZonedDateTime , yang membuang informasi zona waktu
  • ada masalah lain, dengan semua JDBC API. Itulah bagaimana objek TIMESTAMP , DATE , TIME seharusnya diambil, yaitu menggunakan kelas java.sql.{Timestamp,Date,Time} . Semua kelas diperluas dari java.util.Date . Adakah yang ingat bagaimana Calendar diperkenalkan dan metode java.util.Date berurusan dengan tahun/bulan/hari/jam/menit/detik di mana sudah usang? Untuk alasan yang bagus (dan saya tidak bermaksud Calendar menyelesaikan semua masalah).

    • Anda tidak dapat mengambil java.sql.Timestamp dari database, jika _JVM time zone_ Anda tidak mengamati waktu lokal tersebut. Jadi aplikasi yang berjalan di AS dapat menyimpan nilai stempel waktu 2017-03-26 02:30:00 (tanpa zona!) di beberapa basis data bersama, tetapi aplikasi yang berjalan di Eropa (dengan misalnya Europe/Berlin sebagai zona JVM) tidak akan dapat mengambil stempel waktu ini, karena ada DST di Eropa pada waktu itu.

    • oh, hal yang sama berlaku untuk java.sql.Date , karena ini adalah kelas yang hampir identik. java.sql.Date mewakili tanggal seolah-olah itu adalah java.sql.Timestamp pada tengah malam, tetapi terkadang tidak ada tengah malam. Ada zona dengan perubahan DST di tengah malam (baik saat ini atau di masa lalu).

    • menurut Anda java.sql.Time bebas dari masalah ini, karena ini mewakili waktu yang diambil sebagai stempel waktu pada 01-01-01? Sayangnya tidak, karena ada zona yang cukup bagus untuk memiliki perubahan kebijakan pada tanggal tersebut (misalnya America/Bahia_Banderas , America/Hermosillo ). Jika JVM adalah salah satu zona ini, program yang menggunakan JDBC tidak akan dapat mengambil nilai TIME tertentu.

Non-solusi adalah mengambil menggunakan API lama JDBC dan mengonversinya ke kelas baru. Tapi ini umumnya salah:

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

Ini mengkompilasi dan berfungsi dengan baik, kecuali ini tidak menyelesaikan masalah yang dijelaskan di atas (bahkan mengambil tanggal tidak berfungsi, jika zona JVM adalah Pacific/Apia dan tanggal diambil adalah 2011-12-30 ;)

Sekarang, untuk solusi yang muncul. ResultSet memiliki API yang kurang populer ini yang memungkinkan Anda meminta driver JDBC untuk mengonversi tipe untuk Anda:

  • 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

Ini tampaknya berfungsi dengan driver JDBC untuk PostgreSQL, MySQL, Oracle, dan H2. Dan, ajaib, menghindari masalah "tidak terwakili di zona JVM" yang dijelaskan di atas.
Meskipun konversi ini belum diimplementasikan dalam misalnya driver SQL Server, saya pikir ini dapat dijadikan pemetaan _the_ default untuk kelas Waktu Java yang dikirimkan oleh JDBI.

Catatan:
Spesifikasi JDBC 4.2 tidak mengamanatkan bahwa driver harus mengimplementasikan ini. Namun, spesifikasi mengharuskan PreparedStatement.setObject dan RowSet.setObject menerima instance kelas Waktu Java dan memperlakukannya dengan benar, jadi driver tetap harus mendukung kelas ini secara eksplisit.

Itu keren! Perhatian utama saya adalah bahwa mengubah pendekatan ini dapat bermanifestasi sebagai regresi bagi pengguna yang menggunakan driver esoterik. Tapi mungkin dengan pesan yang sesuai pada catatan rilis, kita bisa membuat perubahan kecil yang secara teknis melanggar atas nama melakukan sesuatu dengan Cara yang Benar...

@stevenschlansker Anda benar. Saya pikir JDBI bisa memberikan

  • rangkaian pemetaan opsional yang dapat dipasang oleh pengguna untuk memulihkan perilaku asli
  • beberapa komentar yang sesuai dalam catatan rilis (atau bahkan versi utama bump)

Mari kita simpan ke versi minor, kami baru saja merilis 3, dan ini hanya perubahan yang melanggar jika Anda salah menganggapnya ... ;)

Hanya untuk memutar ulang seperti apa yang saya dengar:

  • Pindahkan pemeta java.time bawaan yang ada ke dalam plugin terpisah (saya suka YoloTimePlugin )
  • Tambahkan pembuat peta bawaan baru di tempat mereka yang menggunakan ResultSet.getObject(column, type) alih-alih mengonversi dari tipe java.sql.
  • Dokumentasikan perubahan besar ini dalam catatan rilis: jelaskan dampak dari perubahan ini dan vendor database mana yang akan terpengaruh, dan apa yang perlu dilakukan pengguna untuk mengurangi masalah

Aku bisa berada di belakang ini.

Kami masih belum menjawab pertanyaan tentang mengikat objek tanggal/waktu ini. Apa pun yang kita ubah tentang hasil pemetaan _keluar_ database perlu dicerminkan dalam cara kita mengikat argumen tanggal/waktu _ke_ pernyataan SQL.

Apa pun yang kita ubah tentang hasil pemetaan dari database perlu dicerminkan dalam cara kita mengikat argumen tanggal/waktu ke dalam pernyataan SQL.
@qualidafial , pertanyaan yang sangat bagus. Saya belum menguji ini. Ini secara eksplisit dicakup oleh spesifikasi JDBC 4.2, jadi _harus berfungsi™_.

Ini secara eksplisit dicakup oleh spesifikasi JDBC 4.2, jadi _harus berfungsi™_.

Ini menganggap bahwa pelaksana driver JDBC mengikuti spesifikasi dengan sempurna. Saya belum menemukan implementasi driver JDBC tanpa bug.

Saya merasa akan terlalu rumit untuk menyediakan plugin dengan pembuat peta untuk setiap database dan bahkan versi yang berbeda yang memiliki dukungan berbeda untuk tipe data. Mungkin pendekatan batu tulis yang lebih kosong dapat berhasil: Anda mulai dengan instance Jdbi tanpa pembuat peta yang sudah diinstal sebelumnya, dan artefak inti menyediakan banyak pembuat peta berbeda yang dapat Anda pilih secara manual untuk diinstal, beberapa memiliki logika berbeda untuk menangani tipe data yang sama - dapatkan/ setObject, get/setX, konversi ke tipe lain, dll. Anda harus mencari tahu sendiri pembuat peta mana yang terbaik untuk basis data (versi) dan logika aplikasi Anda, dan menggunakan pengujian unit untuk tetap memeriksanya.

Pada dasarnya itulah yang sudah saya lakukan sekarang dalam proyek saya. Ada beberapa pembuat peta yang sudah diinstal sebelumnya di Jdbi yang tidak berfungsi dengan db saya dan saya tidak membutuhkannya untuk saat ini, jadi saya sebenarnya telah menggantinya dengan pabrik argumen/pemeta yang melemparkan UnsupportedOperationException, dan yang lainnya telah saya timpa dengan lebih baik implementasi (lihat di bawah).

Ini akan menjadi solusi bagi mereka yang ingin akrab dengan db mereka untuk memastikan semuanya benar-benar berfungsi, dan tidak akan mengubah apa pun untuk orang yang menginginkan barang ke Just Werk™ (sejauh yang sebenarnya):

  • tambahkan metode ke instance Jdbi untuk menghapus semua mapper/argumen mereka (clean slate)
  • memaparkan impls mapper/arg bawaan saat ini untuk kami instal secara manual
  • terus tambahkan impls mapper alternatif ke artefak inti saat permintaan meningkat dan biarkan orang menginstalnya sendiri, menghasilkan apa pun yang mungkin seperti di bawah ini

Dengan melakukan ini, saya telah berhasil menemukan ... terlalu banyak poin di driver hsqldb di mana mereka menyimpang dari spesifikasi mereka sendiri (dilaporkan dan diperbaiki di sumbernya, masih menunggu mereka akhirnya menerbitkan artefak yang diperbarui), dan berhasil di sekitar ketidaksempurnaan itu dengan menemukan sendiri logika pemetaan yang berfungsi.

// 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

Bagaimana? Misalnya, Anda dapat menyediakan SetObjectArgumentFactory yang perlu diinisialisasi dengan serangkaian kelas yang harus diaktifkannya, dan segala macam variasi logika pemetaan untuk banyak tipe data, dengan beberapa perilaku yang dapat dikonfigurasi jika berlaku. Semua orang senang. Dibutuhkan beberapa pekerjaan dari pengguna akhir, tetapi saya merasa senang mengetahui jdbi melakukan persis apa yang saya inginkan dan apa yang didukung oleh database saya.

Saya merasa akan terlalu rumit untuk menyediakan plugin dengan pembuat peta untuk setiap database dan bahkan versi yang berbeda yang memiliki dukungan berbeda untuk tipe data.

Saya ingin memiliki plugin untuk banyak vendor database. Ayo, ayo semua: jika database Anda membutuhkan/menginginkan beberapa penyesuaian untuk mengadaptasi Jdbi dengan keistimewaan vendor database atau driver JDBC-nya, kami ingin mendengarnya. Atau lebih baik lagi, kami ingin menarik permintaan! :)

Poin bonus jika database Anda didukung langsung oleh TravisCI sehingga kami benar-benar dapat menjalankan pengujian terhadapnya: https://docs.travis-ci.com/user/database-setup/

Mengenai saran "batu tulis kosong" Anda, saya hanya memiliki sedikit keberatan:

  • Saya mungkin akan menempatkan metode clearMappings() langsung di RowMappers , ColumnMappers , Arguments , dan JdbiCollectors kelas konfigurasi alih-alih pada Jdbi , dan saya akan menamainya clear() .
  • Saya agak ragu untuk membuat pembuat peta, argumen, dan kolektor bawaan menjadi publik. Beberapa dari mereka memiliki nama atau desain miring yang kami hindari karena mereka internal. Saya mungkin ingin melakukan refactor beberapa sebelum menjadikannya bagian dari API.
  • Saya mempertanyakan apakah papan tulis kosong benar-benar diperlukan. Semua kelas registry Jdbi menggunakan pendekatan last-registered-wins, jadi selalu mungkin untuk mengganti perilaku out-of-the-box. Dalam hal itu, papan tulis kosong terasa sedikit berlebihan.

@jdbi/kontributor ada orang lain yang mau mempertimbangkan?

Saya menyertakan ide batu tulis kosong untuk menghindari penggunaan mapper default secara tidak sengaja jika Anda lupa mendaftarkan salah satu pilihan Anda. Saya lebih suka memiliki NotImplementedException daripada impl default. Kemenangan terakhir itu bagus dan semuanya, tetapi tidak ada cara untuk mengetahui mana yang perlu Anda tolak jika Anda tidak menginginkannya.

Ini tidak seperti sakit untuk memiliki. Jika orang tidak menginginkan pendekatan itu, mereka tidak perlu memanggil metode yang jelas dan tidak ada perubahan untuk mereka. Ini hanya untuk mereka yang lebih menyukai cara kerja tanpa default.

Saya setuju bahwa kita seharusnya tidak hanya membuat pembuat peta yang ada menjadi publik. Jika kita memilih untuk memberikan opsi clean slate, kita harus menggabungkan mapper dan binder ke dalam potongan Plugin wajar, PrimitivesPlugin , BoxedPrimitivesPlugin , CollectionsPlugin , apa pun.

Kemudian, kita dapat menambahkan pabrik baru untuk jdbi "dasar" tanpa konfigurasi sama sekali, dan memodifikasi pabrik yang ada untuk menggunakan ini dan menambahkan WholeJdbiEnchiladaPlugin .

Saya agak menentang 'clear' kecuali kami dapat menunjukkan kasus-kasus di mana sulit untuk membangunnya secara aditif -- terasa seperti bau kode bagi saya.

Saya agak menentang 'clear' kecuali kami dapat menunjukkan kasus-kasus di mana sulit untuk membangunnya secara aditif -- terasa seperti bau kode bagi saya.

Nah jika Anda menambahkan pabrik jdbi no-preconfig terpisah, maka tidak akan sulit untuk membangunnya secara aditif sehingga kita tidak memerlukan clear() memang.

Benar, saya pikir kita sepakat di sini, saya hanya mengungkapkan preferensi menambahkan metode pabrik "bersih" baru di atas gaya clear() .

Jadi, apakah ini menyelesaikan masalah semua orang? Secara pribadi saya pikir rencananya terdengar sangat seksi.

  • buat Jdbi no-defaults (melempar pengecualian pada hampir semua hal)
  • buat semua mapper dan pengikat yang ada (dan penangan tx dll) dapat dipasang ( PrimitivesPlugin , BoxedPrimitivesPlugin , dll), sebagai bundel plugin dan sebagai kelas individual
  • memberikan beberapa implementasi alternatif ( UTCJavaTimePlugin vs LocalJavaTimePlugin vs ConvertJavaTimeToUtilDatePlugin , GetObjectMapper.forClasses(Class... cs) , SetObjectArgumentFactory.forClasses(Class... cs) , NullsToDefaultsPrimitivesPlugin vs NullThrowsExceptionPrimitivesPlugin ) dan mengekspos mereka dengan cara yang sama (dalam plugin dan individual), sehingga orang dapat menyusun logika pemetaan total yang diinginkan, hanya mengambil apa yang mereka inginkan. Berpotensi banyak konfigurasi mapper diperlukan di sini, seperti strategi berbeda untuk menangani null ilegal atau zona waktu yang hilang, dan kemungkinan perbedaan lainnya
  • mungkin membuat plugin bundel khusus db, sehingga pengguna dengan basis data+versi populer dapat memulai dari Jdbi tanpa konfigurasi dan pemasangan satu baris yang dikenal skema pemetaan bagus untuk db mereka ( HsqlDb2_4_0Plugin ), lagi dengan opsi konfigurasi untuk berbagai strategi
  • dan buat semuanya kompatibel dengan hanya membuat metode pabrik saat ini melakukan prakonfigurasi yang kita miliki sekarang ( BuiltInGenericPreconfigurationPlugin ), di samping metode pabrik tanpa konfigurasi.

buat Jdbi tanpa default

Saya tidak memiliki pendapat yang sangat kuat, tetapi ini semua terdengar sangat kompleks dari perspektif pengguna. Pengguna perlu memahami berbagai kemungkinan pemetaan untuk jenis yang ingin mereka gunakan dan memilih yang sesuai. Ini sulit, terutama ketika temporal sedang dimainkan -- bukanlah hal yang sepele untuk memahami kemungkinan opsi yang berbeda.

Pengguna perlu memahami berbagai pemetaan yang mungkin untuk jenis yang ingin mereka gunakan dan memilih yang sesuai

Tidak, hanya jika mereka mau. Metode pabrik yang ada akan terus menghasilkan instance Jdbi dengan mapper prainstal yang sama persis seperti yang mereka lakukan sekarang. Kami hanya akan mendapatkan tambahan metode pabrik konfigurasi DIY, dan orang-orang yang memilihnya perlu mengetahui keintiman pemetaan. Akan ada pertengahan juga, di mana Anda mendapatkan contoh DIY dan hanya menginstal YourDbAndVersionPlugin dan roll dengan apa pun yang dilakukannya. Penjelasan panjang saya sebagian besar adalah internal jdbi dan penggunaan lanjutan, bukan baseline.

TLDR: Anda masih dapat melakukan Jdbi.create(dataSource) dan Anda tidak perlu memberikan pujian tambahan tentang hal itu yang belum Anda berikan. Orang lain hanya akan memilih untuk Jdbi.createBlank(dataSource).install(x).install(y).install(z)...

Saya setuju, kecuali saya pikir kita tidak harus menghentikan pabrik yang ada, saya yakin sebagian besar pengguna akan terus menggunakannya karena perilaku "di luar kotak" cukup bagus.

Cukup adil

@TheRealMarnes Seluruh percakapan ini dimulai dengan tipe data JSR-310 yang tidak didukung langsung oleh JDBC.

Saya pikir ada konsensus tentang menghapus pemeta dan argumen Java.time yang salah, dan memasukkannya ke dalam plugin alih-alih bawaan.

Apakah Anda masih ingin mengejar itu?

Hanya yang java.time? Plugin JavaTime?

Ya, sebuah plugin hanya untuk tipe Java.time, tetapi dinamai untuk mengomunikasikan bahwa argumen dan pembuat peta adalah implementasi yang naif dan lossy seperti yang dijelaskan oleh @findepi .

SimplisticJavaTimePlugin ?

Menunggu dengan ini sampai PR saya yang lain diurus ... Ini agak terlalu banyak pada saat yang sama.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat