2016-04-08 56 views
1

我有一個SQL查詢,可以準確獲取我需要的數據。問題是我們試圖在JPA Criteria API中表達所有查詢以保持可移植性,並且我無法弄清楚如何映射這個特定的查詢。SQL查詢過於複雜以便在JPA Criteria API中顯示?

問題是JPA Criteria API子查詢類缺少CriteriaQuery類所具有的multiselect()方法。正如你在SQL查詢中看到的那樣,我計算了子查詢中實體中不存在的字段。因此,我無法檢索這些字段。

如果有人知道解決方案或可以提供指導,或者即使有人可以驗證我在JPA Criteria API中實現的功能是不可能的,我也會非常感激。

的SQL:

SELECT w.NAME AS 'wave_name', 
    Count(*) AS 'num_lines', 
    Sum(qty_ordered) AS 'num_units', 
    Count(DISTINCT unit_of_work_id) AS 'num_units_of_work', 
    Sum(completed_units) AS 'completed_units', 
    (Sum(completed_units) + Sum(qty_scratched))/Sum(qty_ordered) AS 'perc_completed_units' 
FROM (SELECT t.id, 
      t.wave_id, 
      t.quantity_requested AS 'qty_ordered', 
      t.quantity_scratched AS 'qty_scratched', 
      t.unit_of_work_id  AS 'unit_of_work_id', 
      Ifnull(m.quantity, 0) AS 'qty_picked', 
      CASE 
      WHEN Ifnull(m.quantity, 0) > quantity_requested THEN 
      quantity_requested 
      ELSE Ifnull(m.quantity, 0) 
      END     AS 'completed_units' 
    FROM task t 
      LEFT OUTER JOIN (SELECT move.task_id, 
            Sum(quantity) AS 'quantity' 
          FROM move 
          GROUP BY task_id) m 
         ON m.task_id = t.id) s 
    JOIN wave w 
    ON w.id = s.wave_id 
GROUP BY w.name; 

的實體:

@Entity 
@Table(name = "task") 
public class Task { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="id") 
    private Long id; 

    @ManyToOne (cascade = CascadeType.ALL) 
    @JoinColumn (name = "wave_id", nullable = false) 
    private Wave wave; 

    @ManyToOne (cascade = CascadeType.ALL) 
    @JoinColumn (name = "unit_of_work_id", nullable = false) 
    private UnitOfWork unitOfWork; 

    @OneToMany (cascade = CascadeType.ALL, mappedBy = "task") 
    private Set<Move> moves = new HashSet<Move>(); 

    @Column (name = "quantity_requested") 
    private Long quantityRequested; 

    @Column (name = "quantity_scratched") 
    private Long quantityScratched; 
} 

@Entity 
@Table(name = "wave") 
public class Wave { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id") 
    private Long id; 

    @Column(name = "name") 
    private String name; 

    @OneToMany(mappedBy = "wave", cascade = CascadeType.ALL) 
    private Set<Task> tasks = new HashSet<Task>(); 
} 

@Entity 
@Table(name = "unit_of_work") 
public class UnitOfWork { 

    @Id 
    @GeneratedValue (strategy = GenerationType.IDENTITY) 
    @Column (name = "id") 
    private Long id; 

    @OneToMany(mappedBy = "unitOfWork", cascade = CascadeType.ALL) 
    private Set<Task> tasks = new HashSet<Task>(); 
} 

@Entity 
@Table(name = "move") 
public class Move { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="id") 
    private Long id; 

    @ManyToOne (cascade = CascadeType.ALL) 
    @JoinColumn (name = "task_id", nullable = false) 
    private Task task; 

    @Column (name = "quantity") 
    private Long quantity; 
} 
+0

爲什麼只有條件查詢爲什麼不使用命名參數或原生查詢方式?如果查詢很大,則使用標準方法是沒有意義的。 – Arun

+0

我正在處理的項目有一個基於標準的模塊,它有助於一般性地將過濾器應用於支持系統中特定數據網格的「預先準備好的」條件查詢。直到這一點,「罐裝」查詢相對簡單,這種方法已經足夠。但隨着更復雜的需求呈現出來,我一直在努力使其對於所有查詢都足夠通用。我認爲,在我的例子中,像這樣的疑問就是對這種方法的有力證據。 – Jon

+0

我已經提供了一個示例作爲條件的替代方法,請檢查它。在這種情況下,我認爲標準不是一個好方法。 – Arun

回答

0

我要說的命名參數或本地查詢方法這一點。

例如:

命名參數:

public interface Repo extends JpaRepository<AEntity, String> { 
    @Query("select a from AEntity a where a.BEntity.name = :name") 

    public aMethod(@Param("name") String name) 
    } 

OR

本地查詢方法:

public interface Repo extends JpaRepository<AEntity, String> {  
    @Query(value = "select * from Tablename t where t.name = :name", nativeQuery=true) 

    public aMethod(@Param("name") String name) 
    } 

檢查這個鏈接,如果您使用的春天JPA

http://docs.spring.io/spring-data/data-jpa/docs/1.4.x/reference/htmlsingle/#jpa.named-parameters