1 Pertanyaan: Mengubah perilaku java.sql.Date setelah peningkatan klien OJBC

pertanyaan dibuat di Fri, Aug 22, 2014 12:00 AM

Setelah peningkatan klien OJDBC dari versi 11.2.0 ke 12.1.0, saya mengalami perilaku yang berbeda dalam mengikat objek java.sql.Date ke PreparedStatement.

Dalam pernyataan yang disiapkan, variabel host "f.plan_date =?" harus diikat dengan nilai objek java.util.Date, menjadi input yang diperoleh di tempat lain dalam kode. Tipe data kolom dalam tabel Oracle adalah "DATE" dan hanya bagian tanggal yang harus diperhitungkan - waktu tidak relevan.

Saya menerjemahkan objek java.util.Date dalam objek java.sql.Date dengan cara berikut:  statementRegisterJobs.setDate(3, new java.sql.Date(planDate.getTime()));

Ini berfungsi baik dengan klien 11.2.0. Namun, hal-hal yang cenderung salah setelah peningkatan ke 12.1.0. Tidak ada catatan yang diambil lagi. Setelah berjam-jam debug, saya menemukan bahwa masalah itu terkait dengan variabel tanggal. Cara kerja berikut memberi saya catatan saya kembali:  statementRegisterJobs.setDate(3, java.sql.Date.valueOf("2014-08-21"));

Bisakah seseorang mengklarifikasi perilaku ini? Objek java.util.Date akhirnya dapat memiliki komponen waktu, dan saya memiliki perasaan yang tidak terdefinisi bahwa ini bisa terkait dengan masalah entah bagaimana. Di sisi lain, item berikut harus menyatakan bahwa komponen waktu diabaikan dalam java.sql.Date, tidak peduli bagaimana objek itu dibangun ...

  • Di Java 6 API untuk java.sql.Date, saya menemukan pernyataan berikut: "Metode ini sudah usang dan tidak boleh digunakan karena nilai-nilai SQL Date tidak memiliki komponen waktu." (metode 'getHours ()'). Jadi ini berarti bahwa aspek waktu diabaikan ketika mengubah java.util.Date menjadi java.sql.Date.
  • Ini dikonfirmasi oleh informasi dalam dokumentasi konstruktor: "Membangun objek Tanggal menggunakan nilai waktu milidetik yang diberikan. Jika nilai milidetik yang diberikan berisi informasi waktu, pengemudi akan mengatur komponen waktu ke waktu di zona waktu default (zona waktu mesin virtual Java yang menjalankan aplikasi) yang sesuai dengan nol GMT. "
  • Selain itu, saya tidak bisa mendapatkan aspek waktu yang mungkin dari objek java.sql.Date: toString () memberi saya hanya tanggal, getHours () melempar pengecualian.
  • Dan bagaimana hal ini terkait dengan pembaruan di klien JDBC?

Pikiran apa pun dihargai :) Terima kasih banyak sebelumnya.

    
8
  1. Hanya beberapa ide dasar: kami bermain-main dengan tanggal juga, tetapi instantiate kalender Gregorian terlebih dahulu, mengatur semua fragmen waktu ke 0 dan menginisialisasi pernyataan yang disiapkan dari objek ini dengan setTimestamp(...) . Berfungsi sempurna, tetapi DB bukan ORA tetapi MySql.
    2014-08-22 15: 33: 35Z
  2. Mungkin lebih bermanfaat untuk merujuk ke dokumen untuk konstruktor , yang dengan cara bundaran mengatakan waktunya dilucuti. Sudahkah Anda memverifikasi waktu aktual parameter tersebut di sisi Oracle? Apakah ini waktu planDate (jika ada), atau mungkin ini masalah zona waktu?
    2014-08-22 15: 34: 10Z
  3. Dalam database, hanya tanggal yang disimpan, tidak ada waktu. Saya kira itu mungkin default ke 00:00:00 lalu. (Jika saya memeriksa informasi bidang dengan Toad, 'null time' ditandai.)
    2014-08-22 15: 40: 03Z
  4. Tanggal selalu memiliki waktu, bahkan jika tengah malam. Saya bertanya apa yang dilihat basis data sebagai nilai pengikatan. Anda dapat meminta select to_char(?, 'YYYY-MM-DD HH24:MI:SS') from dual dan mengikat nilai planDate yang sama, dan melihat apa yang dikembalikan, dan bagaimana perbandingannya dengan apa yang Anda harapkan berada di planDate?
    2014-08-22 16: 33: 22Z
  5. Setelah mendefinisikan variabel-variabel berikut: java.util.Date utilDate = new Date();, java.sql.Date sqlDate1 = new java.sql.Date(utilDate.getTime());, dan java.sql.Date sqlDate2 = java.sql.Date.valueOf("2014-08-27"); dan mengikat mereka ke pernyataan yang Anda ajukan (SELECT to_char(?, 'YYYY-MM-DD HH24:MI:SS') testDate FROM dual), saya rasa saya mendapat wawasan lebih dalam masalah ini.
    2014-08-27 12: 55: 11Z
    1 Jawaban                              1                         

    Menentang apa yang dinyatakan Java API, saat membuat objek java.sql.Date dengan melewatkan nilai waktu milidetik, aspek waktu tampaknya disimpan dalam objek dan tidak default ke nol saat menggunakan driver OJDBC 12.1.0 .

    Ini adalah tes yang saya atur:

     
    java.util.Date utilDate = new Date();
    java.sql.Date sqlDate1 = new java.sql.Date(utilDate.getTime());
    java.sql.Date sqlDate2 = java.sql.Date.valueOf("2014-08-27");
    

    Saya menyiapkan pernyataan berikut (SELECT to_char(?, 'YYYY-MM-DD HH24:MI:SS') testDate FROM dual), mengikat sqlDate1 dan sqlDate2 dan mendapatkan hasil berikut.

    1. Dengan versi driver 11.2.0

      • sqlDate1: 2014-08-27 00:00:00
      • sqlDate2: 2014-08-27 00:00:00
    2. Dengan driver versi 12.1.0

      • sqlDate1: 2014-08-27 14:47:29
      • sqlDate2: 2014-08-27 00:00:00

    Ini tidak sejalan dengan dokumentasi di API:

      

    Jika nilai milidetik yang diberikan berisi informasi waktu, driver   akan mengatur komponen waktu ke waktu di zona waktu default (   zona waktu mesin virtual Java yang menjalankan aplikasi) itu   sesuai dengan nol GMT .

    Namun, mengetahui hal ini saya dapat memperbaiki masalah dengan memaksa informasi waktu objek tanggal sql menjadi tengah malam.

        
    6
    2014-08-27 15: 23: 29Z
    1. Anda mungkin juga ingin mempertimbangkan untuk mengajukan laporan bug dengan Oracle.
      2014-08-27 15: 35: 38Z
    2. Ini adalah threda yang relevan di forum Oracle: community.oracle.com/thread/3826309?start=0&tstart=0 Tampaknya itu disengaja dan tidak dianggap sebagai bug ...
      2016-05-17 13: 12: 54Z
sumber ditempatkan sini