Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Masalah konversi Oracle SQL DATE menggunakan iBATIS melalui Java JDBC

Info lengkap (dan ini lebih kompleks daripada yang dijelaskan di sini dan mungkin bergantung pada versi tertentu dari driver Oracle yang digunakan) ada di jawaban Richard Yee di sini - [tautan kedaluwarsa sekarang ke Nabble]

Cepat ambil sebelum kedaluwarsa dari nabble...

Roger, Lihat:http://www.Oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01

Khususnya:Tipe Data Sederhana Apa yang terjadi dengan DATE dan TIMESTAMP? Bagian ini membahas tipe data sederhana. :-)

Sebelum 9.2, driver Oracle JDBC memetakan tipe DATE SQL ke java.sql.Timestamp. Ini masuk akal karena tipe Oracle DATE SQL berisi informasi tanggal dan waktu seperti halnya java.sql.Timestamp. Pemetaan yang lebih jelas ke java.sql.Date agak bermasalah karena java.sql.Date tidak menyertakan informasi waktu. RDBMS juga tidak mendukung tipe SQL TIMESTAMP, jadi tidak ada masalah dengan pemetaan DATE ke Timestamp.

Dalam 9.2 TIMESTAMP dukungan ditambahkan ke RDBMS. Perbedaan antara DATE dan TIMESTAMP adalah TIMESTAMP menyertakan nanodetik dan DATE tidak. Jadi, mulai 9.2, DATE dipetakan ke Date dan TIMESTAMP dipetakan ke Timestamp. Sayangnya jika Anda mengandalkan nilai DATE untuk memuat informasi waktu, ada masalah.

Ada beberapa cara untuk mengatasi masalah ini:

Ubah tabel Anda untuk menggunakan TIMESTAMP alih-alih DATE. Ini mungkin jarang memungkinkan, tetapi ini adalah solusi terbaik saat ini.

Ubah aplikasi Anda untuk menggunakan defineColumnType untuk mendefinisikan kolom sebagai TIMESTAMP daripada DATE. Ada masalah dengan ini karena Anda benar-benar tidak ingin menggunakan defineColumnType kecuali Anda harus melakukannya (lihat Apa itu defineColumnType dan kapan saya harus menggunakannya?).

Ubah aplikasi Anda untuk menggunakan getTimestamp daripada getObject. Ini adalah solusi yang baik jika memungkinkan, namun banyak aplikasi berisi kode generik yang bergantung pada getObject, sehingga tidak selalu memungkinkan.

Setel properti koneksi V8Compatible. Ini memberitahu driver JDBC untuk menggunakan pemetaan lama daripada yang baru. Anda dapat menyetel tanda ini sebagai properti koneksi atau properti sistem. Anda menyetel properti koneksi dengan menambahkannya ke objek java.util.Properties yang diteruskan ke DriverManager.getConnection atau ke OracleDataSource.setConnectionProperties. Anda menyetel properti sistem dengan menyertakan opsi -D di baris perintah java Anda.

java -Doracle.jdbc.V8Compatible="true" MyAppOracle JDBC 11.1 memperbaiki masalah ini. Dimulai dengan rilis ini, driver memetakan kolom SQL DATE ke java.sql.Timestamp secara default. Tidak perlu mengatur V8Compatible untuk mendapatkan pemetaan yang benar. V8Compatible sangat usang. Anda seharusnya tidak menggunakannya sama sekali. Jika Anda menyetelnya ke true, itu tidak akan merugikan apa pun, tetapi Anda harus berhenti menggunakannya.

Meskipun jarang digunakan seperti itu, V8Compatible ada bukan untuk memperbaiki masalah DATE to Date tetapi untuk mendukung kompatibilitas dengan database 8i. Database 8i (dan yang lebih lama) tidak mendukung tipe TIMESTAMP. Pengaturan V8Compatible tidak hanya menyebabkan SQL DATE dipetakan ke Timestamp ketika dibaca dari database, tetapi juga menyebabkan semua Timestamps dikonversi ke SQL DATE saat ditulis ke database. Karena 8i tidak didukung, driver 11.1 JDBC tidak mendukung mode kompatibilitas ini. Karena alasan ini, V8Compatible tidak didukung.

Seperti disebutkan di atas, driver 11.1 secara default mengonversi SQL DATE ke Timestamp saat membaca dari database. Ini selalu merupakan hal yang benar untuk dilakukan dan perubahan pada 9i adalah sebuah kesalahan. Driver 11.1 telah kembali ke perilaku yang benar. Bahkan jika Anda tidak menyetel V8Compatible di aplikasi Anda, Anda tidak akan melihat perbedaan perilaku dalam banyak kasus. Anda mungkin melihat perbedaan jika Anda menggunakan getObject untuk membaca kolom DATE. Hasilnya akan menjadi Timestamp daripada Date. Karena Timestamp adalah subclass dari Date, ini biasanya tidak menjadi masalah. Di mana Anda mungkin melihat perbedaan adalah jika Anda mengandalkan konversi dari DATE ke Tanggal untuk memotong komponen waktu atau jika Anda melakukan toString pada nilainya. Jika tidak, perubahan harus transparan.

Jika karena alasan tertentu aplikasi Anda sangat sensitif terhadap perubahan ini dan Anda hanya harus memiliki perilaku 9i-10g, ada properti koneksi yang dapat Anda atur. Setel mapDateToTimestamp ke false dan driver akan kembali ke perilaku default 9i-10g dan memetakan DATE ke Date.

Jika memungkinkan, Anda harus mengubah jenis kolom menjadi TIMESTAMP, bukan DATE.

-Richard

Roger Voss menulis:Saya memposting pertanyaan/masalah berikut di stackoverflow, jadi jika ada yang tahu resolusinya, sebaiknya lihat jawabannya di sana:

Masalah konversi Oracle SQL DATE menggunakan iBATIS melalui Java JDBC

Berikut uraian masalahnya:

Saat ini saya sedang bergulat dengan masalah konversi DATE Oracle sql menggunakan iBATIS dari Java.

Saya menggunakan driver tipis Oracle JDBC ojdbc14 versi 10.2.0.4.0. iBATIS versi 2.3.2. Java 1.6.0_10-rc2-b32.

Masalahnya berkisar pada kolom tipe DATE yang dikembalikan oleh potongan SQL ini:

PILIH *FROM TABLE(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) pesan sebelum tanggal_tanggal

Pemanggilan prosedur paket mengembalikan kursor ref yang sedang dibungkus dalam TABLE ke tempat yang kemudian mudah untuk membaca hasil yang ditetapkan seolah-olah kueri pemilihan terhadap tabel.

Di PL/SQL Developer, salah satu kolom yang dikembalikan, FROM_DATE, dari tipe SQL DATE, memiliki ketepatan waktu:

Tue Dec 16 23:59:00 PST 2008

Tetapi ketika saya mengakses ini melalui iBATIS dan JDBC, nilainya hanya mempertahankan presisi hingga hari ini:

Tue Dec 16 12:00:00 AM PST 2008

Ini lebih jelas ketika ditampilkan seperti ini:

Seharusnya:1229500740000 milidetik sejak epochTuesday, December 16, 2008 11:59:00 PM PST

Tapi mendapatkan ini sebagai gantinya:1229414400000 milidetik sejak epochTuesday, 16 Desember 2008 12:00:00 AM PST (sebagai turunan dari kelas java.sql.Date)

Tidak peduli apa yang saya coba, saya tidak dapat mengekspos presisi penuh kolom DATE ini untuk dikembalikan melalui Java JDBC dan iBATIS.

Dari apa iBATIS memetakan adalah ini:

FROM_DATE :2008-12-03 :class java.sql.Date

Pemetaan iBATIS saat ini adalah ini:

Saya juga sudah mencoba:

atau

Tetapi semua pemetaan yang dicoba menghasilkan nilai Tanggal terpotong yang sama. Seolah-olah JDBC telah melakukan kerusakan kehilangan presisi data bahkan sebelum iBATIS menyentuhnya.

Jelas saya kehilangan beberapa presisi data saya dengan melalui JDBC dan iBATIS yang tidak terjadi ketika saya tinggal di PL/SQL Developer menjalankan cuplikan SQL yang sama dengan skrip pengujian. Tidak dapat diterima sama sekali, sangat membuat frustrasi, dan akhirnya sangat menakutkan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Membuat Kursor Ref Lemah PL/SQL Di Database Oracle

  2. tangkap pengecualian DB di aplikasi JSF + EJB

  3. Mendapatkan kesalahan saat Menjalankan Paket

  4. Perbedaan antara literal N'String' vs U'String' di Oracle

  5. Oracle UTL_SMTP:Kirim Email dengan Contoh Lampiran Menggunakan Otentikasi Oracle Wallet