Pertanyaan Hibernate: Bagaimana mengatur nilai parameter query NULL dengan HQL?


bagaimana saya bisa mengatur Parameter Hibernate ke "null"? Contoh:

Query query = getSession().createQuery("from CountryDTO c where c.status = :status  and c.type =:type")
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

Dalam kasus saya, String status bisa nol. Saya telah men-debug ini dan hibernate kemudian menghasilkan string / query SQL seperti ini ....status = null... Namun ini tidak Bekerja di MYSQL, karena pernyataan SQL yang benar harus "status is null"(Mysql tidak mengerti status = null dan mengevaluasi ini ke false sehingga tidak ada catatan yang akan dikembalikan untuk kueri, sesuai dengan dokumen mysql yang telah saya baca ...)

Pertanyaan saya:

  1. Kenapa tidak Hibernate terjemahkan string null dengan benar ke "is null" (dan membuat dan membuat "= null")?

  2. Apa cara terbaik untuk menulis ulang query ini sehingga tidak aman? Dengan nullsafe saya berarti bahwa dalam kasus bahwa "status" String adalah nol daripada seharusnya membuat "adalah nol"?

Terima kasih banyak! Tim


54
2018-01-23 14:21


asal


Jawaban:


  1. Saya percaya hibernate pertama menerjemahkan query HQL Anda ke SQL dan hanya setelah itu mencoba untuk mengikat parameter Anda. Artinya, ini tidak akan dapat menulis ulang kueri param = ? untuk param is null.

  2. Coba gunakan Kriteria api:

    Criteria c = session.createCriteria(CountryDTO.class);
    c.add(Restrictions.eq("type", type));
    c.add(status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status));
    List result = c.list();
    

37
2018-01-24 09:49



Ini bukan masalah khusus Hibernate (hanya bersifat SQL), dan YES, ada solusi untuk SQL dan HQL:

@Peter Lang memiliki ide yang tepat, dan Anda memiliki kueri HQL yang benar. Saya kira Anda hanya perlu menjalankan bersih baru untuk mengambil perubahan permintaan ;-)

Kode di bawah ini benar-benar berfungsi dan sangat bagus jika Anda menyimpan semua pertanyaan Anda di orm.xml

from CountryDTO c where ((:status is null and c.status is null) or c.status = :status) and c.type =:type

Jika String parameter Anda nol maka queri akan memeriksa apakah status baris juga null. Kalau tidak, itu akan membandingkan dengan tanda yang sama.

Catatan:

Masalahnya mungkin merupakan permainan kata-kata MySql yang spesifik. Saya hanya diuji dengan Oracle.

Query di atas mengasumsikan bahwa ada baris tabel di mana c.status adalah null

Klausa tempat diprioritaskan sehingga parameter diperiksa terlebih dahulu.

Nama parameter 'type' mungkin kata cadangan dalam SQL tetapi seharusnya tidak masalah karena diganti sebelum query dijalankan.

Jika Anda perlu melewati: status di mana_judul sama sekali; Anda dapat mengkode seperti ini:

from CountryDTO c where (:status is null or c.status = :status) and c.type =:type

dan itu setara dengan:

sql.append(" where ");
if(status != null){
  sql.append(" c.status = :status and ");
}
sql.append(" c.type =:type ");

24
2018-02-06 02:50



Itu javadoc untuk setParameter(String, Object) eksplisit, mengatakan bahwa nilai Objek harus tidak nol. Sayang sekali bahwa itu tidak membuang pengecualian jika null dilewatkan masuk, meskipun.

Alternatifnya adalah setParameter(String, Object, Type), yang mana tidak izinkan nilai nol, meskipun saya tidak yakin apa Type parameter akan paling tepat di sini.


12
2018-01-23 14:27



Saya tidak mencoba ini, tetapi apa yang terjadi ketika Anda menggunakan :status dua kali untuk diperiksa NULL?

Query query = getSession().createQuery(
     "from CountryDTO c where ( c.status = :status OR ( c.status IS NULL AND :status IS NULL ) ) and c.type =:type"
)
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

4
2018-01-23 14:30



Sepertinya Anda harus menggunakannya is null di HQL, (yang dapat menyebabkan permutasi kompleks jika ada lebih dari satu parameter dengan potensi nol.) tetapi di sini adalah solusi yang mungkin:

String statusTerm = status==null ? "is null" : "= :status";
String typeTerm = type==null ? "is null" : "= :type";

Query query = getSession().createQuery("from CountryDTO c where c.status " + statusTerm + "  and c.type " + typeTerm);

if(status!=null){
    query.setParameter("status", status, Hibernate.STRING)
}


if(type!=null){
    query.setParameter("type", type, Hibernate.STRING)
}

4
2018-01-24 11:05



HQL mendukung bersatu, memungkinkan untuk solusi yang buruk seperti:

where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')

4
2017-08-22 13:39



Untuk kueri HQL yang sebenarnya:

FROM Users WHERE Name IS NULL

3
2018-03-11 17:01



Kamu dapat memakai

Restrictions.eqOrIsNull("status", status)

insted dari

status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)

1
2017-07-30 11:30



Berikut adalah solusi yang saya temukan di Hibernate 4.1.9. Saya harus mengirimkan parameter ke permintaan saya yang dapat memiliki nilai NULL kadang-kadang. Jadi saya lulus menggunakan:

setParameter("orderItemId", orderItemId, new LongType())

Setelah itu, saya menggunakan klausa di mana berikut dalam permintaan saya:

where ((:orderItemId is null) OR (orderItem.id != :orderItemId))

Seperti yang Anda lihat, saya menggunakan metode Query.setParameter (String, Object, Type), di mana saya tidak bisa menggunakan Hibernate.LONG yang saya temukan di dokumentasi (mungkin itu pada versi yang lebih lama). Untuk set lengkap opsi tipe parameter, periksa daftar kelas penerapan antarmuka org.hibernate.type.Type.

Semoga ini membantu!


1
2017-11-15 14:36



ini sepertinya berfungsi sebagai baik ->

@Override
public List<SomeObject> findAllForThisSpecificThing(String thing) {
    final Query query = entityManager.createQuery(
            "from " + getDomain().getSimpleName() + " t  where t.thing = " + ((thing == null) ? " null" : " :thing"));
    if (thing != null) {
        query.setParameter("thing", thing);
    }
    return query.getResultList();
}

Btw, saya cukup baru dalam hal ini, jadi jika karena alasan apa pun ini bukan ide yang bagus, beri tahu saya. Terima kasih.


-1
2018-06-26 01:56