Saya memiliki metode Java umum dengan metode tanda tangan berikut:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Ini membuka koneksi, membangun PreparedStatement
menggunakan pernyataan sql dan parameter dalam queryParams
array panjang variabel, menjalankannya, cache ResultSet
(dalam a CachedRowSetImpl
), menutup koneksi, dan mengembalikan set hasil cache.
Saya memiliki pengecualian dalam penanganan metode yang mencatat kesalahan. Saya mencatat pernyataan sql sebagai bagian dari log karena ini sangat membantu untuk debugging. Masalah saya adalah bahwa log variabel String sql
log pernyataan template dengan? S bukan nilai yang sebenarnya. Saya ingin mencatat pernyataan aktual yang dieksekusi (atau mencoba dieksekusi).
Jadi ... Apakah ada cara untuk mendapatkan pernyataan SQL aktual yang akan dijalankan oleh PreparedStatement
? ( Tanpa membangunnya sendiri. Jika saya tidak dapat menemukan cara untuk mengakses PreparedStatement's
SQL, saya mungkin akan berakhir membangunnya sendiri di catch
es saya .)
sumber
Jawaban:
Menggunakan pernyataan yang disiapkan, tidak ada "permintaan SQL":
Tetapi tidak ada pembangunan kembali permintaan SQL nyata yang sebenarnya - baik di sisi Jawa, maupun di sisi database.
Jadi, tidak ada cara untuk mendapatkan pernyataan SQL yang disiapkan - karena tidak ada SQL seperti itu.
Untuk tujuan debugging, solusinya adalah:
sumber
Ini tidak didefinisikan dalam kontrak JDBC API, tetapi jika Anda beruntung, driver JDBC yang dimaksud dapat mengembalikan SQL lengkap hanya dengan menelepon
PreparedStatement#toString()
. YaituSetidaknya driver MySQL 5.x dan PostgreSQL 8.x JDBC mendukungnya. Namun, sebagian besar driver JDBC lainnya tidak mendukungnya. Jika Anda memilikinya, maka taruhan terbaik Anda adalah menggunakan Log4jdbc atau P6Spy .
Atau, Anda juga dapat menulis fungsi generik yang mengambil
Connection
, string SQL dan nilai pernyataan dan mengembalikan aPreparedStatement
setelah masuk string SQL dan nilai-nilai. Contoh kickoff:dan gunakan sebagai
Alternatif lain adalah menerapkan kebiasaan
PreparedStatement
yang membungkus (menghiasi) yang nyataPreparedStatement
pada konstruksi dan menimpa semua metode sehingga memanggil metode yang nyataPreparedStatement
dan mengumpulkan nilai-nilai dalam semuasetXXX()
metode dan dengan malas membangun string SQL "aktual" setiap kali salah satu dari yangexecuteXXX()
metode disebut (cukup bekerja, tapi yang paling IDE menyediakan autogenerators untuk metode dekorator, Eclipse tidak). Akhirnya gunakan saja sebagai gantinya. Itu juga pada dasarnya apa yang P6Spy dan selir sudah lakukan di bawah tenda.sumber
logger.debug(sql + " " + Arrays.asList(values))
- Saya sedang mencari cara untuk mencatat pernyataan sql dengan parameter yang sudah terintegrasi ke dalamnya. Tanpa mengulangi dan mengganti tanda tanya.PreparedStatement
setiap waktu. Bukankah itu cara yang tidak terlalu efisien karena seluruh intinyaPreparedStatement
adalah membuat mereka sekali dan menggunakannya kembali di mana-mana?Saya menggunakan Java 8, JDBC driver dengan konektor MySQL v. 5.1.31.
Saya mungkin mendapatkan string SQL nyata menggunakan metode ini:
Jadi mengembalikan sesuatu seperti ini:
sumber
Apache Derby
?Jika Anda mengeksekusi query dan mengharapkan
ResultSet
(Anda berada di skenario ini, setidaknya) maka Anda hanya dapat memanggilResultSet
'sgetStatement()
seperti:Variabel
executedQuery
akan berisi pernyataan yang digunakan untuk membuatResultSet
.Sekarang, saya menyadari pertanyaan ini sudah cukup lama, tetapi saya harap ini membantu seseorang ..
sumber
Saya telah mengekstrak sql saya dari PreparedStatement menggunakan readyStatement.toString () Dalam kasus saya toString () mengembalikan String seperti ini:
Sekarang saya telah membuat metode (Java 8), yang menggunakan regex untuk mengekstraksi kueri dan nilai dan memasukkannya ke dalam peta:
Metode ini mengembalikan peta tempat kami memiliki pasangan nilai kunci:
Sekarang - jika Anda ingin nilai sebagai daftar, Anda cukup menggunakan:
Jika readyStatement.toString () Anda berbeda dari pada kasus saya, itu hanya masalah "menyesuaikan" regex.
sumber
Menggunakan PostgreSQL 9.6.x dengan driver Java resmi
42.2.4
:Akan menampilkan SQL dengan yang
?
sudah diganti, yang adalah apa yang saya cari. Baru saja menambahkan jawaban ini untuk membahas kasus postgres.Saya tidak akan pernah berpikir itu bisa begitu sederhana.
sumber
Saya menerapkan kode berikut untuk mencetak SQL dari ReadyStatement
sumber
Cuplikan Kode untuk mengonversi SQL PreparedStaments dengan daftar argumen. Ini bekerja untuk saya
sumber
Sangat terlambat :) tetapi Anda bisa mendapatkan SQL asli dari OraclePreparedStatementWrapper oleh
sumber
oracle.jdbc.driver.OraclePreparedStatementWrapper
tidak umum di oracle.jdbc.driver. Tidak dapat diakses dari paket luar. Bagaimana Anda menggunakan Kelas itu?Jika Anda menggunakan MySQL, Anda dapat mencatat kueri menggunakan log kueri MySQL . Saya tidak tahu apakah vendor lain menyediakan fitur ini, tetapi kemungkinan mereka melakukannya.
sumber
Cukup berfungsi:
Tidak apa-apa juga untuk pernyataan yang disiapkan.
sumber
.toString()
dengan beberapa baris tambahan untuk mengelabui pengguna yang tidak ahli, dan sudah dijawab berabad-abad yang lalu.Saya menggunakan Oralce 11g dan tidak bisa mendapatkan SQL final dari PreparedStatement. Setelah membaca @Pascal, jawaban MARTIN saya mengerti mengapa.
Saya baru saja meninggalkan ide menggunakan PreparedStatement dan menggunakan formatter teks sederhana yang sesuai dengan kebutuhan saya. Inilah contoh saya:
Anda mengetahui sqlInParam dapat dibangun secara dinamis dalam (untuk, sementara) loop saya hanya membuatnya sederhana untuk sampai ke titik menggunakan kelas MessageFormat untuk berfungsi sebagai formater template string untuk query SQL.
sumber
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Untuk melakukan ini, Anda memerlukan Koneksi JDBC dan / atau driver yang mendukung logging sql di tingkat rendah.
Lihatlah log4jdbc
sumber