2012-02-08 33 views
8

Tôi có truy vấn phức tạp qua 7 bảng và muốn biết cách triển khai nó trong Hibernate.Hibernate - Truy vấn phức tạp từ nhiều bảng đến một đối tượng

Nỗ lực hiện tại của tôi là tạo truy vấn bằng session.createSQLQuery và tôi sẽ ánh xạ kết quả cho một thực thể cụ thể.

Tôi không chắc chắn cách thực hiện điều đó như trước đây tôi chỉ làm việc với một bảng thành một thực thể. Tôi sẽ cần phải xác định rằng tôi muốn sử dụng một truy vấn phức tạp có thể mở rộng nhiều bảng? Điều đó chỉ đi trong mã của tôi? Tệp hbm.xml của tôi? Tôi không thể nghĩ ra bất cứ điều gì khác ngoài nỗ lực hiện tại của tôi.

Dưới đây là một ví dụ về truy vấn của tôi:

String stringQuery = 
     "select WI.Customer_Id, CU.Card, CU.Code, "+ 
       "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
       "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
       "CO.City_Geo_Level, "+ 
       "CU.Address_id, CA.Name, "+ 
       "CU.Category_Id, "+ 
       "CU.Status, "+ 
       "Sum(MO.Charged_Points) as Charged_Points, "+ 
       "Sum(MO.Total_Money) as Total_Money, "+ 
       "Count(MO.id) as AmountTransWinner "+ 
     "from Promotions_Winner WI "+ 
     "join Customers CU "+ 
      "on WI.Customer_id = CU.id "+ 
     "join Personal_Info PI "+ 
      "on CU.Personal_Info_Id = PI.id "+ 
     "join Address AD "+ 
      "on CU.Address_Id = AD.id "+ 
     "join Countries CO "+ 
      "on AD.country_id = CO.id "+ 
     "join Campaigns CA "+ 
      "on CU.Campaign_Id = CA.id "+ 
     "join Movements MO "+ 
      "on WI.Movement_Id = MO.id "+ 
     "where WI.Promotion_Id = :pPromotionID "+ 
     "group by "+ 
      "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+ 
      "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
      "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
      "CO.City_Geo_Level, "+ 
      "CU.Address_id, CA.Name, "+ 
      "CU.Category_Id, "+ 
      "CU.Status"; 
+0

Vui lòng tham khảo http://stackoverflow.com/questions/21374550/fetching-data-from-multiple-tables-in-hibernate-and-storing-the-result-in-a-bean/21379254 # 21379254 – Touchstone

Trả lời

5

Bạn không cần SQL để thực hiện truy vấn này. HQL sẽ làm tốt. Và truy vấn như vậy trả về một List<Object[]>, mỗi Object[] chứa một hàng của tập hợp kết quả. Vì vậy, bạn sẽ tìm thấy ID khách hàng tại chỉ mục 0, thẻ ở chỉ mục 1, v.v. Bạn chỉ cần lặp lại các hàng và tạo một thể hiện của đối tượng nhẹ của bạn tại mỗi lần lặp.

Xem http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-select

+1

thay vì lặp lại Danh sách và tạo thủ công đối tượng nhẹ của bạn, bạn có thể sử dụng 'chọn new my.package.myLightWeightObject (t1.field1, t2.field2, t3.field3)' và chỉ cần thiết lập hàm tạo cho myLightWeightObject để lấy các trường thích hợp. Bằng cách đó, Hibernate sẽ trả về một List thay cho List cho bạn. – digitaljoel

+0

JB Nizet, vâng, tôi biết, nhưng nếu tôi sử dụng Danh sách và trong tương lai, người khác thêm một trường mới giữa các trường hiện tại, nó không hoạt động nữa. Tôi thích ý tưởng digitaljoel, nhưng tôi không hiểu cách thực hiện. Bạn có thể giải thích thêm một chút không? –

+0

Có. Nếu anh ta thay đổi các bảng cơ sở dữ liệu mà không thay đổi mã, nó sẽ không hoạt động. Thực hiện kiểm tra đơn vị và kiểm tra xem truy vấn có hoạt động như mong đợi trong các thử nghiệm đơn vị hay không. Tôi không biết làm thế nào tôi (hoặc digitaljoel) có thể rõ ràng hơn thế. Bạn không hiểu gì Bạn có ít nhất đã thử một cái gì đó? –

0

Vì vậy, theo như tôi có thể thấy đây là tham gia của 7 bảng. Nếu bạn đang sử dụng chế độ ngủ đông, bạn sẽ ánh xạ từng bảng trong số các bảng này thành các thực thể và sau đó sử dụng @JoinColumn để ánh xạ tới từng phụ thuộc của nó. Đây là loại truy vấn SQL mà ngủ đông là có để ngăn chặn xảy ra.

+0

nhưng tôi có các trường Đếm và Tổng, –

+0

Sau đó, bạn chỉ cần getTotalChargePoints() làm phương thức - đó sẽ là logic nghiệp vụ của bạn. Bằng cách đó bất cứ điều gì cần tổng số cá nhân hoặc đếm hoặc bất cứ điều gì không cần phải gọi truy vấn này mỗi lần. Đối với số đếm bạn thực sự chỉ cần làm List.size() trên bất kỳ bộ sưu tập của các mục nó tham gia (cho một đến nhiều mối quan hệ) –

3

Cuối cùng tôi có thể giải quyết sử dụng mã này:

String stringQuery = 
       "select " + 
         "CU.Card as card, " + 
         "CU.Fidely_Code as fidelyCode, "+ 
         "PI.Identity_Card as identityCard, " + 
         "PI.Name as name, " + 
         "PI.Surname as surname, " + 
         "PI.Gender as gender, "+ 
         "AD.Zip as zip, " + 
         "AD.Geo_Lat as geo_lat, " + 
         "AD.Geo_Long as geo_long, "+ 
         "CO.City_Geo_Level as cityGeoLevel, "+ 
         "CA.Name as campaignName, "+ 
         "CU.Status as status, "+ 
         "Sum(MO.Charged_Points) as pointsCharged, "+ 
         "Sum(MO.Total_Money) as amountPurchase, "+ 
         "Count(MO.id) as amountTransWinner "+ 
       "from Promotions_Winner WI "+ 
       "join Customers CU "+ 
        "on WI.Customer_id = CU.id "+ 
       "join Personal_Info PI "+ 
        "on CU.Personal_Info_Id = PI.id "+ 
       "join Address AD "+ 
        "on CU.Address_Id = AD.id "+ 
       "join Countries CO "+ 
        "on AD.country_id = CO.id "+ 
       "join Campaigns CA "+ 
        "on CU.Campaign_Id = CA.id "+ 
       "join Movements MO "+ 
        "on WI.Movement_Id = MO.id "+ 
       "where WI.Promotion_Id = :pPromotionID "+ 
       "group by "+ 
        "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+ 
        "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
        "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
        "CO.City_Geo_Level, "+ 
        "CU.Address_id, CA.Name, "+ 
        "CU.Category_Id, "+ 
        "CU.Status "; 

     //Query query = this.getSession().createSQLQuery(stringQuery).addEntity("", PromotionsWinnerLittle.class); 
     //Query query = this.getSession().createSQLQuery(stringQuery).setResultSetMapping("PromotionsWinnerLittle"); 
     Query query = this.getSession().createSQLQuery(stringQuery) 
      .addScalar("card", StandardBasicTypes.LONG) 
      .addScalar("fidelyCode", StandardBasicTypes.LONG) 
      .addScalar("identityCard", StandardBasicTypes.STRING) 
      .addScalar("name", StandardBasicTypes.STRING) 
      .addScalar("surname", StandardBasicTypes.STRING) 
      .addScalar("gender", StandardBasicTypes.STRING) 
      .addScalar("zip", StandardBasicTypes.STRING) 
      .addScalar("geo_lat", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("geo_long", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("cityGeoLevel", StandardBasicTypes.LONG) 
      .addScalar("campaignName", StandardBasicTypes.STRING) 
      .addScalar("status", StandardBasicTypes.LONG) 
      .addScalar("pointsCharged", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("amountPurchase", StandardBasicTypes.LONG) 
      .addScalar("amountTransWinner", StandardBasicTypes.LONG)    
      .setResultTransformer(Transformers.aliasToBean(PromotionsWinnerLittle.class)); 

     //Query query = this.getSession().createSQLQuery(stringQuery); 

     query = query.setLong("pPromotionID", promotionID); 

     List lista = query.list(); 

I Just thêm "Như" một phần vào Chọn và addScalar + setResultTransformer

+0

Một vấn đề trong phương pháp này là một lần nếu bạn nhận được dữ liệu dưới dạng nguyên thủy và nếu bạn muốn để ghi dữ liệu này vào một bảng khác được tạo bằng lược đồ của các kiểu do người dùng định nghĩa sẽ tạo ra một vấn đề. – rakeeee

4

của họ là hai cách để làm điều này.

1. Bạn sẽ nhận được một mảng đối tượng danh sách.

List<Object[]> 

Ở đây một phần tử của mảng đại diện cho một hàng truy vấn của bạn.

2. Bạn có thể sử dụng một tính năng hibernate ResultTransformer - Tạo một lớp đơn giản cho đầu ra của truy vấn của bạn. - Tạo Trình tạo kết quả.

Ví dụ:

public class MyResultTransformer implements ResultTransformer { 


/* 
Method to convert to generic type list 
*/ 
    @Override 
    public List<Employee> transformList(List arg0) { 
     List<Employee> employees = new ArrayList<Employee>(); 
     for (Object employee : arg0) { 
      employees.add((Employee) employee); 
     } 
     return employees; 
    } 

    /* 
    Code to transform your query output to Object 
    */ 
    @Override 
    public Employee transformTuple(Object[] arg0, String[] arg1) { 
     System.out.println("MyResultTransformer.transformTuple()"); 
     Employee tempEmp = new Employee(); 
     tempEmp.setEmployee_id((BigInteger) arg0[0]); 
     return tempEmp; 
    } 
} 

- đặt biến áp thành truy vấn.

Query query=session.createSQLQuery("SELECT * FROM employeedetail"); // You can use named query, SQL native also 
     query.setResultTransformer(new MyResultTransformer()); 
      List<Employee> employees=query.list(); 
Các vấn đề liên quan