HQL'de nasıl farklı bir sorgu oluşturursunuz?


100

HQL'de Distinct sorgu oluşturmanın bir yolu var mı? Ya "farklı" anahtar kelimeyi veya başka bir yöntemi kullanarak. Farklılığın HQL için geçerli bir anahtar çalışması olup olmadığından emin değilim, ancak "farklı" SQL anahtar kelimesinin HQL eşdeğerini arıyorum.

Yanıtlar:


124

İşte kullandığımız bir hql parçası. (Kimlikleri korumak için isimler değiştirildi)

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});

Sadece MySQL ile hazırda bekletmeyi kullandım - mssql sorunuyla nasıl başa çıkacağımı bilmiyorum.
Feet

GetHibernateTemplate () işlevi standart API'ye değil, Spring Framework'e aittir. Spring Framework'ü kullanmadan bir eşdeğerini biliyor musunuz?
Matthieu.V

56

distinctHQL'deki anahtar kelimenin doğrudan SQL'deki anahtar kelimeyle eşleşmediğini belirtmek gerekir distinct.

Eğer kullanırsanız distinctHQL anahtar kelime, daha sonra bazen hazırda kullanacağı distinctSQL anahtar sözcüğü, ancak bazı durumlarda bu farklı sonuçlar üretmek için bir sonuç trafo kullanacaktır. Örneğin, bunun gibi bir dış birleşim kullandığınızda:

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

Bu durumda SQL düzeyinde kopyaları filtrelemek mümkün değildir, bu nedenle Hibernate , SQL sorgusu gerçekleştirildikten sonraResultTransformer kopyaları filtrelemek için a kullanır .



16

bir dahaki sefere böyle bir şey yap

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

 List claz = crit.list();

1
Bu yetersizdir: veritabanı düzeyinde tekrarları atmak yerine, verileri tekrarlarla ve tümüyle birlikte veritabanından belleğe çeker ve ardından tekrarları atar; Verilerin ne sıklıkla tekrarladığına bağlı olarak, bu, G / Ç işlemlerini oldukça artırabilir.
Haroldo_OK

9

Ayrıca Criteria.DISTINCT_ROOT_ENTITYHibernate HQL sorgusu ile de kullanabilirsiniz .

Misal:

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

1
Bu yetersizdir: veritabanı düzeyinde tekrarları atmak yerine, verileri tekrarlarla ve tümüyle birlikte veritabanından belleğe çeker ve ardından tekrarları atar; Verilerin ne sıklıkla tekrarladığına bağlı olarak, bu, G / Ç işlemlerini oldukça artırabilir.
Haroldo_OK

4

HQL sorgularıyla birleştirilmiş sonuç dönüştürücüleriyle ilgili bazı sorunlar yaşadım. Denediğimde

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

işe yaramadı. Manuel olarak şu şekilde dönüştürmek zorunda kaldım:

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

Criteria API transformatörleri ile gayet iyi çalıştı.


10
bin'e

3

Ana sorgum modelde şöyle görünüyordu:

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

Ve hala "farklı" olarak düşündüğüm sonuçları alamıyordum. Tablodaki birincil anahtar kombinasyonuna dayalı olarak sadece farklıydılar.

Böylece DaoImplbir satır değişikliği ekledim ve istediğim "farklı" getiriyi elde ettim. Bir örnek 00'ı dört kez görmek yerine şimdi sadece bir kez görüyorum. İşte eklediğim kod 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;       
}

Umarım bu yardımcı olmuştur! Bir kez daha, bu yalnızca projenin hizmet, dao ve model türünü uygulayan kodlama uygulamalarını takip ediyorsanız işe yarayabilir.


2

CUSTOMER_INFORMATION tablosuyla eşlenmiş bir Müşteri Varlığınız olduğunu ve müşterinin farklı firstName listesini almak istediğinizi varsayalım. Aynısını almak için aşağıdaki pasajı kullanabilirsiniz.

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

Umut ediyorum bu yardım eder. Yani burada farklı anahtar kelime kullanmak yerine grup kullanıyoruz.

Ayrıca daha önce, birden çok sütuna uygulamak istediğimde farklı anahtar kelime kullanmayı zor buldum. Örneğin, farklı firstName, lastName ve ardından group by listesini almak istiyorum. Bu durumda farklı kullanmakta zorlandım.


1

Farklı alanları kullanmak için Hazırda Bekletme Sorgu Dili için bir cevabım var. * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE * kullanabilirsiniz. SQL sorgusu kullanırsanız , Dize Listesi döndürür. Varlık Sınıfına göre dönüş değerini kullanamazsınız. Dolayısıyla, bu tür bir Sorunu çözmek için Cevap , SQL ile HQL kullanmaktır .

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

Gönderen SQL sorgusu deyimi bir liste olarak DISTINCT ROUTE_ID ve giriş var. Ve IN sorgusu, IN (Liste) 'den farklı TO_CITY'i filtreler.

İade türü Entity Bean türüdür. Böylece, AutoComplement gibi AJAX'ta yapabilirsiniz .

Her şey yolunda olabilir


1

Ölçüt oluşturucunuzdaki farklı anahtar kelimeyi bu şekilde yapabilirsiniz.

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));

Ve model sınıfınızda alan yapıcısını oluşturun.


0

Select deyiminizde özel bir DTO için yeni anahtar kelime kullanmanız gerekiyorsa ve farklı öğelere ihtiyacınız varsa , aşağıdaki gibi yeninin dışını kullanın:

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

0

Distinct yerine GROUP BY ekleyebilirsiniz

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.