Saya menggunakan Jdbctemplate untuk mengambil nilai String tunggal dari db. Inilah metode saya.
public String test() {
String cert=null;
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
cert = (String) jdbc.queryForObject(sql, String.class);
return cert;
}
Dalam skenario saya, sangat mungkin untuk TIDAK mendapatkan hasil pada kueri saya, jadi pertanyaan saya adalah bagaimana cara mengatasi pesan kesalahan berikut.
EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
Tampaknya bagi saya bahwa saya harus mendapatkan kembali nol daripada membuat pengecualian. Bagaimana cara memperbaikinya? Terima kasih sebelumnya.
sumber
ResultSet.next()
akan dipanggil jika tidak perlu. Dalam kasus ini, menggunakan alatResultSetExtractor
yang jauh lebih efisien.return null
masukcatch(EmptyResultDataAccessException exception){ return null; }
?Anda juga dapat menggunakan a,
ResultSetExtractor
bukanRowMapper
. Keduanya semudah satu sama lain, satu-satunya perbedaan adalah Anda meneleponResultSet.next()
.The
ResultSetExtractor
memiliki manfaat tambahan bahwa Anda dapat menangani semua kasus di mana ada lebih dari satu baris atau tidak ada baris yang dikembalikan.PEMBARUAN : Beberapa tahun berlalu dan saya memiliki beberapa trik untuk dibagikan.
JdbcTemplate
bekerja luar biasa dengan java 8 lambda yang dirancang untuk contoh berikut tetapi Anda dapat dengan mudah menggunakan kelas statis untuk mencapai hal yang sama.Sementara pertanyaannya adalah tentang tipe sederhana, contoh ini berfungsi sebagai panduan untuk kasus umum penggalian objek domain.
Pertama. Misalkan Anda memiliki objek akun dengan dua properti untuk kesederhanaan
Account(Long id, String name)
. Anda mungkin ingin memilikiRowMapper
untuk objek domain ini.Sekarang Anda dapat menggunakan mapper ini secara langsung di dalam metode untuk memetakan
Account
objek domain dari kueri (jt
adalah sebuahJdbcTemplate
instance).Bagus, tapi sekarang kami menginginkan masalah asli kami dan kami menggunakan solusi asli saya menggunakan kembali
RowMapper
untuk melakukan pemetaan untuk kami.Bagus, tetapi ini adalah pola yang mungkin dan ingin Anda ulangi. Jadi, Anda dapat membuat metode pabrik umum untuk membuat yang baru
ResultSetExtractor
untuk tugas tersebut.Membuat
ResultSetExtractor
sekarang menjadi hal yang sepele.Saya harap ini membantu untuk menunjukkan bahwa Anda sekarang dapat dengan mudah menggabungkan bagian-bagian dengan cara yang ampuh untuk membuat domain Anda lebih sederhana.
UPDATE 2 : Gabungkan dengan Opsional untuk nilai opsional, bukan null.
Yang sekarang bila digunakan bisa memiliki yang berikut:
sumber
Itu bukan solusi yang baik karena Anda mengandalkan pengecualian untuk aliran kontrol. Dalam solusi Anda, wajar untuk mendapatkan pengecualian, itu normal untuk memilikinya di log.
sumber
ResultSet.next()
akan dipanggil jika tidak perlu. Dalam kasus ini, menggunakan alatResultSetExtractor
yang jauh lebih efisien.Oke, saya sudah menemukannya. Saya baru saja membungkusnya dengan mencoba menangkap dan mengirim kembali nol.
sumber
Sebenarnya, Anda dapat bermain
JdbcTemplate
dan menyesuaikan metode Anda sendiri sesuka Anda. Saran saya adalah membuat sesuatu seperti ini:Ini berfungsi seperti aslinya
jdbc.queryForObject
, tetapi tanpathrow new EmptyResultDataAccessException
kapansize == 0
.sumber
UserMapper implements RowMapper<String>
.DataAccessUtils.singleResult(...)
adalah apa yang saya cari. ThxSejak mengembalikan null ketika tidak ada data adalah sesuatu yang sering saya lakukan saat menggunakan queryForObject, saya merasa berguna untuk memperluas JdbcTemplate dan menambahkan metode queryForNullableObject yang mirip dengan di bawah ini.
Anda sekarang dapat menggunakan ini di kode Anda dengan cara yang sama seperti Anda menggunakan queryForObject
Saya akan tertarik untuk mengetahui apakah ada orang lain yang menganggap ini ide yang bagus?
sumber
Menggunakan Java 8 atau yang lebih baru, Anda dapat menggunakan
Optional
dan Java Streams.Jadi Anda cukup menggunakan
JdbcTemplate.queryForList()
metode ini, membuat Stream dan menggunakanStream.findFirst()
yang akan mengembalikan nilai pertama dari Stream atau kosongOptional
:Untuk meningkatkan kinerja kueri, Anda bisa menambahkan
LIMIT 1
ke kueri Anda, jadi tidak lebih dari 1 item yang ditransfer dari database.sumber
Anda bisa menggunakan fungsi grup sehingga kueri Anda selalu mengembalikan hasil. yaitu
sumber
Di Postgres, Anda dapat membuat hampir semua kueri nilai mengembalikan nilai atau null dengan membungkusnya:
dan karenanya hindari kerumitan pada pemanggil.
sumber
Karena getJdbcTemplate (). QueryForMap mengharapkan ukuran minimum satu tetapi ketika mengembalikan null, itu menunjukkan EmptyResultDataAccesso perbaiki dis ketika dapat menggunakan logika di bawah ini
sumber
Saya menangani ini sebelumnya & telah diposting di forum musim semi.
http://forum.spring.io/forum/spring-projects/data/123129-frustrated-with-emptyresultdataaccessexception
Saran yang kami terima adalah menggunakan jenis SQlQuery. Berikut adalah contoh dari apa yang kami lakukan saat mencoba mendapatkan nilai dari DB yang mungkin tidak ada.
Di DAO lalu kita sebut saja ...
Performanya tidak jelas, tetapi berfungsi dan rapi.
sumber
Untuk Byron, Anda bisa mencoba ini ..
sumber
untuk membuat
berfungsi, pastikan jdbcTemplate Anda bertipe
sumber
Kita bisa menggunakan query daripada queryForObject, perbedaan utama antara query dan queryForObject adalah query yang mengembalikan daftar Object (berdasarkan tipe pengembalian Row mapper) dan daftar tersebut bisa kosong jika tidak ada data yang diterima dari database sementara queryForObject selalu mengharapkan hanya satu objek diambil dari db bukan nol atau beberapa baris dan jika hasilnya kosong maka queryForObject melempar EmptyResultDataAccessException, saya telah menulis satu kode menggunakan kueri yang akan mengatasi masalah EmptyResultDataAccessException dalam kasus hasil null.
sumber
IMHO mengembalikan a
null
adalah solusi yang buruk karena sekarang Anda memiliki masalah dalam mengirim dan menafsirkannya di klien ujung depan (kemungkinan). Saya mengalami kesalahan yang sama dan saya mengatasinya hanya dengan mengembalikan fileList<FooObject>
. Saya duluJDBCTemplate.query()
.Di ujung depan (klien web Angular), saya cukup memeriksa daftar dan jika kosong (panjang nol), perlakukan sebagai tidak ada catatan yang ditemukan.
sumber
Saya baru saja menangkap "EmptyResultDataAccessException" ini
lalu Anda dapat memeriksa:
sumber