Làm cách nào để bạn tạo một truy vấn Khác biệt trong HQL


99

Có cách nào để tạo truy vấn Phân biệt trong HQL không. Bằng cách sử dụng từ khóa "khác biệt" hoặc một số phương pháp khác. Tôi không chắc liệu phân biệt có phải là một keywork hợp lệ cho HQL hay không, nhưng tôi đang tìm kiếm tương đương với HQL của từ khóa SQL "diff".

Câu trả lời:


124

Đây là đoạn mã hql mà chúng tôi sử dụng. (Tên đã được thay đổi để bảo vệ danh tính)

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

Tôi chỉ từng sử dụng chế độ ngủ đông với MySQL - không chắc chắn cách giải quyết vấn đề mssql.
Chân

56

Cần lưu ý rằng distincttừ khóa trong HQL không ánh xạ trực tiếp với distincttừ khóa trong SQL.

Nếu bạn sử dụng distincttừ khóa trong HQL, thì đôi khi Hibernate sẽ sử dụng distincttừ khóa SQL, nhưng trong một số trường hợp, nó sẽ sử dụng một biến kết quả để tạo ra các kết quả khác biệt. Ví dụ: khi bạn đang sử dụng một phép nối bên ngoài như thế này:

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

Không thể lọc ra các bản sao ở cấp SQL trong trường hợp này, vì vậy Hibernate sử dụng a ResultTransformerđể lọc các bản sao sau khi truy vấn SQL đã được thực hiện.



16

làm điều gì đó như thế này vào lần sau

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

 List claz = crit.list();

Đó là điều tối ưu: thay vì loại bỏ các lần lặp lại ở cấp cơ sở dữ liệu, nó sẽ chỉ kéo dữ liệu từ cơ sở dữ liệu vào bộ nhớ với các lần lặp lại và tất cả, rồi loại bỏ các lần lặp lại sau đó; tùy thuộc vào tần suất dữ liệu lặp lại, điều đó có thể làm tăng các hoạt động I / O lên khá nhiều.
Haroldo_OK

9

Bạn cũng có thể sử dụng Criteria.DISTINCT_ROOT_ENTITYvới truy vấn Hibernate HQL.

Thí dụ:

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

1
Đó là điều tối ưu: thay vì loại bỏ các lần lặp lại ở cấp cơ sở dữ liệu, nó sẽ chỉ kéo dữ liệu từ cơ sở dữ liệu vào bộ nhớ với các lần lặp lại và tất cả, rồi loại bỏ các lần lặp lại sau đó; tùy thuộc vào tần suất dữ liệu lặp lại, điều đó có thể làm tăng các hoạt động I / O lên khá nhiều.
Haroldo_OK

4

Tôi đã gặp một số vấn đề với máy biến áp kết quả kết hợp với truy vấn HQL. Khi tôi cố gắng

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

nó đã không hoạt động. Tôi đã phải chuyển đổi thủ công như thế này:

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

Với Criteria API, máy biến áp hoạt động tốt.


để đạt được 10k (:
timmz

3

Truy vấn chính của tôi trông giống như thế này trong mô hình:

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

Và tôi vẫn không nhận được kết quả mà tôi cho là "khác biệt". Chúng chỉ khác biệt dựa trên tổ hợp khóa chính trên bảng.

Vì vậy, DaoImpltôi đã thêm một thay đổi một dòng và cuối cùng nhận được lợi nhuận "khác biệt" mà tôi muốn. Một ví dụ là thay vì nhìn thấy 00 bốn lần, bây giờ tôi chỉ nhìn thấy nó một lần. Đây là mã tôi đã thêm vào 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;       
}

Tôi hy vọng điều này đã giúp! Một lần nữa, điều này có thể chỉ hoạt động nếu bạn đang tuân theo các phương pháp mã hóa triển khai dịch vụ, dao và loại mô hình của dự án.


2

Giả sử bạn có một Đối tượng khách hàng được ánh xạ tới bảng CUSTOMER_INFORMATION và bạn muốn nhận danh sách Tên khách hàng đầu tiên riêng biệt. Bạn có thể sử dụng đoạn mã dưới đây để làm tương tự.

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

Tôi hy vọng nó sẽ giúp. Vì vậy, ở đây chúng tôi đang sử dụng nhóm theo thay vì sử dụng từ khóa riêng biệt.

Ngoài ra, trước đây tôi thấy khó sử dụng từ khóa riêng biệt khi tôi muốn áp dụng nó cho nhiều cột. Ví dụ, tôi muốn lấy danh sách firstName riêng biệt, lastName sau đó nhóm theo sẽ đơn giản hoạt động. Tôi đã gặp khó khăn trong việc sử dụng khác biệt trong trường hợp này.


1

Tôi đã có câu trả lời cho Ngôn ngữ truy vấn ngủ đông để sử dụng các trường Riêng biệt. Bạn có thể sử dụng * CHỌN DISTINCT (TO_CITY) TỪ FLIGHT_ROUTE *. Nếu bạn sử dụng truy vấn SQL , nó sẽ trả về Danh sách chuỗi. Bạn không thể sử dụng nó giá trị trả về bởi Lớp thực thể. Vì vậy, Câu trả lời để giải quyết loại vấn đề đó là sử dụng HQL với SQL .

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

Từ câu lệnh truy vấn SQL, nó nhận DISTINCT ROUTE_ID và đầu vào dưới dạng Danh sách. Và truy vấn IN lọc TO_CITY riêng biệt khỏi IN (Danh sách).

Loại trả về là loại thực thể Bean. Vì vậy, bạn có thể thực hiện nó trong AJAX chẳng hạn như AutoComplement .

Có thể tất cả đều ổn


1

Bạn có thể cho bạn từ khóa riêng biệt trong trình tạo tiêu chí của bạn như thế này.

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

Và tạo phương thức khởi tạo trường trong lớp mô hình của bạn.


0

Nếu bạn cần sử dụng từ khóa mới cho DTO tùy chỉnh trong câu lệnh đã chọn của mình và cần các yếu tố khác biệt , hãy sử dụng từ khóa mới bên ngoài mới như sau-

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

0

Bạn chỉ cần thêm GROUP BY thay vì Distinction

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.