2010-11-08 63 views
12

Hi ai có thể chỉ cho tôi để làm sao chúng ta có thể vượt qua một trật tự quy định tại khoản như tham số được đặt tên để HQLHibernate Đặt tên Query Sắp xếp theo tham số

Ex:

trình:

select tb from TransportBooking as tb 

and TIMESTAMP(tb.bookingDate, tb.bookingTime) >= current_timestamp() order by tb.bookingDate 

Không hoạt động :

select tb from TransportBooking as tb 

and TIMESTAMP(tb.bookingDate, tb.bookingTime) >= current_timestamp() order by :order 

Trả lời

18

Không được hỗ trợ, thông số đầu vào chỉ được phép trong WHEREHAVING mệnh đề và bạn không thể sử dụng các tham số cho mệnh đề ORDER BY. Hoặc nếu tôi rephrase, bạn không thể sử dụng các tham số cho cột, chỉ có giá trị. Vì vậy, một trong hai:

  • có càng nhiều tên truy vấn như đơn đặt hàng loại tốt
  • CONCATENATE chuỗi trật tự vào chuỗi truy vấn
  • Sử dụng tiêu chí truy vấn
+0

Có cảm ơn vì API tiêu chí là giải pháp. Hibernate được chứng minh là một ORM rất hạn chế. –

+0

Có một khả năng mới và [thú vị] (https://stackoverflow.com/a/43900567/5483217) kể từ JPA 2.1 – toKrause

6

Hãy thử lưu trữ các truy vấn có tên mà không có trật tự theo mệnh đề, nhận chuỗi truy vấn và thêm thứ tự bởi các phần mệnh đề tại thời gian chạy.

Brian Fields giải thích nó trong blog của mình: http://brainfields.blogspot.com/2009/08/order-by-in-hibernate-named-queries.html

tôi đã đóng gói ý tưởng cho dự án của tôi:

private static final Pattern badQueryPattern = Pattern.compile("[^\\p{ASCII}]*"); 

public static String getNamedQueryString(EntityManager em, String queryName) throws SQLException { 
    Query tmpQuery = em.createNamedQuery(queryName); 
    SQLQuery sqlQuery = tmpQuery.unwrap(SQLQuery.class); 
    String queryString = sqlQuery.getQueryString(); 
    if (badQueryPattern.matcher(queryString).matches()) { 
     throw new SQLException("Bad query string."); 
    } 

    return queryString; 
} 


public static Query getNamedQueryOrderedBy(EntityManager em, String queryName, Map<String, Boolean> columnNames) throws SQLException { 

    StringBuilder sb = new StringBuilder(); 
    sb.append(ORDER_BY_CLAUSE_START); 

    int limit = columnNames.size(); 
    int i = 0; 
    for (String columnName: columnNames.keySet()) { 
     sb.append(columnName); 

     if (columnNames.get(columnName)) 
      sb.append(" ASC"); 
     else 
      sb.append(" DESC"); 

     if (i != (limit - 1)) { 
      sb.append(", \n"); 
     } 
    } 
    Query jpaQuery = em.createNativeQuery(getNamedQueryString(em, queryName) 
       + sb.toString() 
       ); 

    return jpaQuery; 
} 
+1

Tốt. Đối với JPA 2 với Hibernate 4, tôi sử dụng 'org.hibernate.Query sqlQuery = tmpQuery.unwrap (org.hibernate.Query.class);' để tránh 'java.lang.ClassCastException: org.hibernate.internal.QueryImpl không thể truyền đến org.hibernate.SQLQuery'. – Arjan

1

Bạn có thể muốn hạn chế lĩnh vực sắp xếp để những người bạn có trong bạn mô hình. Trong dự án của tôi, tôi đã làm điều này tĩnh:

public static boolean isColumnName(Object domain, String columnName) { 
    Field[] fields = domain.getClass().getDeclaredFields(); 
    for (Field field : fields) { 
     Annotation[] annotations = field.getAnnotations(); 
     for (Annotation annotation : annotations) { 
      if (annotation instanceof Column) { 
       Column column = (Column) annotation; 
       String foundColumnName; 
       if (column.name() != null && !column.name().isEmpty()) { 
        foundColumnName = column.name(); 
       } else { 
        foundColumnName = field.getName(); 
       } 
       if (columnName.toUpperCase().equals(
        foundColumnName.toUpperCase())) { 
        return true; 
       } 
      } 
     } 
    } 
    return false; 
} 

Members tên trường trên bạn Dal trước concat chuỗi vào JPQL hoặc HQL bạn sẽ tránh sql injection hoặc các vấn đề hơn nữa

0

Nó có thể được thực hiện như

này
order by CASE :orderBy 
      WHEN 'pato_id' THEN PATO.id 
      WHEN 'last_update_dt' THEN PATO.last_update_dt 
    END desc 

và bạn có thể vượt qua "pato_id" hoặc "last_update_dt" trong hàm setString như thế này

q.setString("orderBy", "last_update_dt"); 
or 
q.setString("orderBy", "pato_id"); 

Điều này làm việc với MS SQL Server, không chắc chắn về những người khác.

+0

Vì vậy, đây không phải là một giải pháp SQL chung – SaSConsul

+0

Vâng, tôi đã đưa ra một ý tưởng, nếu nó giúp, tốt. Nếu không, nó chắc chắn sẽ giúp người dùng SQL Server. –