Bagaimana Anda membuat kueri Berbeda di HQL


100

Apakah ada cara untuk membuat kueri Berbeda di HQL. Baik dengan menggunakan kata kunci "berbeda" atau metode lain. Saya tidak yakin apakah perbedaan adalah keywork yang valid untuk HQL, tetapi saya mencari HQL yang setara dengan kata kunci SQL "berbeda".

Jawaban:


124

Berikut cuplikan dari hql yang kami gunakan. (Nama telah diubah untuk melindungi identitas)

String queryString = "select distinct f from Foo f inner join foo.bars as b" +
                " where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
        return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});

Saya hanya pernah menggunakan hibernate dengan MySQL - tidak yakin bagaimana menangani masalah mssql.
Kaki

56

Perlu dicatat bahwa distinctkata kunci di HQL tidak langsung dipetakan ke distinctkata kunci di SQL.

Jika Anda menggunakan distinctkata kunci di HQL, terkadang Hibernate akan menggunakan distinctkata kunci SQL, tetapi dalam beberapa situasi akan menggunakan transformator hasil untuk menghasilkan hasil yang berbeda. Misalnya saat Anda menggunakan gabungan luar seperti ini:

select distinct o from Order o left join fetch o.lineItems

Dalam kasus ini, tidak mungkin untuk menyaring duplikat di tingkat SQL, jadi Hibernate menggunakan ResultTransformeruntuk menyaring duplikat setelah kueri SQL dilakukan.



16

lakukan sesuatu seperti ini lain kali

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();

Itu kurang optimal: alih-alih membuang pengulangan di tingkat database, ia hanya akan menarik data dari database ke memori dengan pengulangan dan seterusnya, dan kemudian membuang pengulangan setelahnya; tergantung seberapa sering data diulang, yang dapat meningkatkan operasi I / O cukup banyak.
Haroldo_OK

9

Anda juga dapat menggunakan Criteria.DISTINCT_ROOT_ENTITYdengan kueri Hibernate HQL.

Contoh:

Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();

1
Itu kurang optimal: alih-alih membuang pengulangan di tingkat database, ia hanya akan menarik data dari database ke memori dengan pengulangan dan seterusnya, dan kemudian membuang pengulangan setelahnya; tergantung seberapa sering data diulang, yang dapat meningkatkan operasi I / O cukup banyak.
Haroldo_OK

4

Saya memiliki beberapa masalah dengan transformator hasil yang digabungkan dengan kueri HQL. Ketika saya mencoba

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

itu tidak berhasil. Saya harus mengubah secara manual seperti ini:

final List found = trans.transformList(qry.list());

Dengan API Kriteria, transformator bekerja dengan baik.


untuk sampai ke 10k (:
timmz

3

Permintaan utama saya terlihat seperti ini dalam model:

@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd", 
    query = "select distinct i from CentralFinancialAgencyAccountCd i")

Dan saya masih belum mendapatkan apa yang saya anggap sebagai hasil yang "berbeda". Mereka hanya dibedakan berdasarkan kombinasi tombol utama di atas tabel.

Jadi, DaoImplsaya menambahkan perubahan satu baris dan akhirnya mendapatkan pengembalian "berbeda" yang saya inginkan. Contohnya adalah daripada melihat 00 empat kali, sekarang saya hanya melihatnya sekali. Ini kode yang saya tambahkan ke DaoImpl:

@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {

    Session session = (Session) entityManager.getDelegate();
    org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
    q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
    List<CacheModelBase> codes;
    codes = q.list();
    return codes;       
}

Saya harap ini membantu! Sekali lagi, ini mungkin hanya berfungsi jika Anda mengikuti praktik pengkodean yang mengimplementasikan layanan, dao, dan jenis model proyek.


2

Misalkan Anda memiliki Entitas Pelanggan yang dipetakan ke tabel CUSTOMER_INFORMATION dan Anda ingin mendapatkan daftar nama depan pelanggan yang berbeda. Anda dapat menggunakan potongan di bawah ini untuk mendapatkan yang sama.

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

Saya harap ini membantu. Jadi di sini kami menggunakan grup dengan alih-alih menggunakan kata kunci yang berbeda.

Juga sebelumnya saya merasa sulit untuk menggunakan kata kunci yang berbeda ketika saya ingin menerapkannya ke beberapa kolom. Misalnya saya ingin mendapatkan daftar firstName yang berbeda, lastName maka kelompok dengan hanya akan bekerja. Saya mengalami kesulitan dalam menggunakan perbedaan dalam kasus ini.


1

Saya mendapat jawaban untuk Hibernate Query Language untuk menggunakan bidang Berbeda. Anda dapat menggunakan * PILIH DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Jika Anda menggunakan kueri SQL , itu mengembalikan Daftar String. Anda tidak dapat menggunakannya untuk mengembalikan nilai dengan Kelas Entitas. Jadi Jawaban untuk mengatasi jenis Masalah tersebut adalah menggunakan HQL dengan SQL .

FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);

Dari pernyataan query SQL didapat DISTINCT ROUTE_ID dan input sebagai List. Dan kueri IN memfilter TO_CITY yang berbeda dari IN (Daftar).

Jenis pengembalian adalah jenis Entity Bean. Jadi Anda bisa melakukannya di AJAX seperti AutoComplement .

Semoga semuanya baik-baik saja


1

Anda dapat membuat kata kunci yang berbeda dalam pembuat kriteria Anda seperti ini.

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));

Dan buat konstruktor bidang di kelas model Anda.


0

Jika Anda perlu menggunakan kata kunci baru untuk DTO kustom dalam pernyataan pemilihan Anda dan membutuhkan elemen yang berbeda , gunakan new outside of new seperti berikut-

select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...

0

Anda cukup menambahkan GROUP BY alih-alih Distinct

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.