2010-01-09 33 views
5

Tôi có một tiêu chí truy vấn, tham gia bảng B thứ hai, để chọn các thực thể từ bảng A. Vấn đề là, truy vấn này trả về một số thực thể từ bảng A nhiều lần. Nhưng tôi cần kết quả là khác biệt.Thêm một nhóm theo tiêu chuẩn Hibernate-Query mà không cần chiếu

Sử dụng tiêu chí.DISTINCT_ROOT_ENTITY là vô ích, bởi vì bộ lọc này sẽ lọc ra nhiều lần xuất hiện sau khi truy vấn SQL được thực hiện. Vì vậy, khi tôi giới hạn kết quả của mình thành 20 lần truy cập, tôi kết thúc chỉ với 4 lần truy cập, mặc dù có nhiều mục nhập hơn, phù hợp với truy vấn của tôi.

Trong SQL thuần túy, tôi có thể thêm "GROUP BY ID" vào truy vấn và mọi thứ đều ổn, vì việc nối bảng B chỉ được sử dụng, để chọn các thực thể từ bảng A. Nhưng với tiêu chí-API tôi không thể làm điều này. Cách duy nhất để thêm "GROUP BY" là sử dụng Projections. Nhưng sau đó, tôi kết thúc với các giá trị vô hướng, không phải với một ví dụ thực sự của lớp học của tôi. Sử dụng một hạn chế SQL không hoạt động, hoặc bởi vì hibernate thêm một "1 = 1" bogous sau "GROUP BY" của tôi -nhưng. :(

Bất kỳ ý tưởng?

+0

'GROUP BY', theo định nghĩa, bao gồm tổng hợp dữ liệu, đó là lý do tại sao Phép chiếu là cần thiết. Có lẽ nếu bạn đã thêm chi tiết hơn về các bảng và truy vấn SQL bạn muốn Hibernate tạo, chúng tôi có thể tư vấn tốt hơn. – skaffman

+0

Tôi có một sự kiện lớp. Lớp này có một danh sách các ngày. (Thực ra, các Ngày này là lớp DateWrapper đặc biệt, kết thúc ngày và thêm một Id, vì hibernate không thể kết hợp các bộ sưu tập có giá trị vào lúc này). Tôi muốn truy vấn các sự kiện và tìm tất cả sự kiện có một hoặc nhiều sự kiện giữa x và y. Khi tôi grap truy vấn SQL, được tạo ra bởi tiêu chí-API và thêm một "GROUP BY id", nó thực hiện chính xác, những gì tôi đang tìm kiếm. Nhưng tôi không thể tìm thấy bất kỳ cách nào để tranh luận Hibernate vào việc thêm GROUP BY! –

Trả lời

0

Có thể viết truy vấn SQL thực tế mà Hibernate có thể sử dụng trở lại các thực thể. Vì vậy, nếu bạn thực sự cần, bạn có thể bỏ qua HQL và viết chính xác truy vấn mà bạn muốn với GROUP của bạn . BY trong nó

Xem here để biết chi tiết

Ví dụ, bạn có thể xác định một điều gì đó truy vấn như thế này trong tập tin hbm.xml của bạn:.

<sql-query name="exampleQuery"> 
<query-param name="param" type="int"/> 
<return alias="x" class="foo.bar.X"/> 
<return alias="y" class="foo.bar.Y"/> 
    <![CDATA[ 
     select {x.*}, {y.*} 
     from XEntity x 
     inner join YEntity y on y.xId = x.id 
     where y.value = :param 
    ]]> 
</sql-query> 

Lưu ý {x. } và {y.} cú pháp viết tắt để chọn tất cả các thuộc tính của thực thể X và pháp nhân Y

+0

Cảm ơn câu trả lời của bạn :) nhưng tôi không sử dụng HQL. Tôi đang sử dụng API tiêu chí và tôi bị ràng buộc với nó, bởi vì truy vấn phải được biên dịch động! Do đó, tôi cần phải tìm cách để cho Hibernate nhóm các kết quả theo thuộc tính id, mà không sử dụng Projections, vì tôi cần các cá thể thực của các lớp của tôi như reslut, chứ không phải các giá trị vô hướng. –

+0

Cũng có thể chỉ định một truy vấn SQL tự nhiên theo chương trình chứ không phải là truy vấn được đặt tên như được hiển thị ở trên - mặc dù không phải bằng cách sử dụng API tiêu chí. – alasdairg

1

Bạn đã cố gắng sử dụng một cái gì đó như thế này?

 ICriteria criteria = dc.GetExecutableCriteria(RepositoryInstance.Session) 
           .SetProjection(
            Projections.Distinct(Projections.ProjectionList() 
             .Add(Projections.Property("Prop1"),"Prop1") 
             .Add(Projections.Property("Prop2"),"Prop2") 
             .Add(Projections.Property("Prop3"),"Prop3") 
             .Add(Projections.Property("Prop4"),"Prop4"))); 
result = criteria.List(); 

Bạn có thể tự động thêm thuộc tính thông qua phản ánh của lớp học.

Điều này tạo ra SQL như thế này: select distinct prop1,prop2,prop3,prop4 from yourClass

Tôi không bao gồm DetachedCriteria dc vì đó là không thích hợp.

1

GROUP BY WITHOUT PROJECTION: Điều này không có ý nghĩa, trong nhiều câu trả lời bạn có thể tìm thấy, Nhưng hầu hết mọi người không muốn sử dụng phép chiếu, vì nó yêu cầu họ chiếu từng thuộc tính, nhưng yêu cầu là một hạt đậu phải được chiếu. (và trả về kết quả). Ví dụ dưới đây tôi đã cố gắng project yêu cầu bean làm đối tượng kết quả.

Tôi đã đạt được kết quả tương tự với một chút mẹo tôi tin, Trước tiên tôi đã cố gắng áp dụng nhóm mà không cần chiếu nhưng tôi đã không tìm thấy giải pháp, vì vậy tôi phải dựa vào Dự đoán.

Dưới đây là những gì tôi muốn đạt được

select p.* FROM parent p INNER JOIN child c ON p.id_parent=c.id_father 
WHERE c.child_name like '%?%' AND p.parent_name like '%?%' 
group by p.id_parent 

Trong mã Java Tôi muốn p.* là một lớp Parent đó là entity bean của tôi và tôi muốn nó là duy nhất, một cách là có được danh sách kết quả trong một Đặt, nhưng tôi không thích cách này vì nhiều lý do :)

Vì vậy, tôi đã tạo Tiêu chí từ Child.class thay vì Parent.class và mẹo này đã hiệu quả đối với tôi.

Criteria c = session.createCriteria(Child.class,"c");// starting from Child 
    c.add(Restrictions.like("childName", "abc", MatchMode.ANYWHERE)); 
    c.createAlias("parent", "p"); //remember parent is an attribute in Child.class 
    c.add(Restrictions.like("p.parentName", "xyz", MatchMode.ANYWHERE)); 
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("parent"))); //projecting parent which is an attribute of Child.class 

    List<Parent> result = c.list(); //get the result 
    for (Parent p: result) { 
     System.out.println(p); 
    } 

Nếu bạn vẫn chưa có ý tưởng ở đây là các lớp Lớp phủ thực thể được ánh xạ của tôi.

package com.mazhar.beans; 

import static javax.persistence.GenerationType.IDENTITY; 

import java.util.List; 

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

@Entity 
@Table(name = "parent") 
public class Parent { 
    private Integer idParent; 
    private String parentName; 
    private List<Child> childs; 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id_parent") 
    public Integer getIdParent() { 
     return idParent; 
    } 
    public void setIdParent(Integer idParent) { 
     this.idParent = idParent; 
    } 

    @Column(name = "parent_name") 
    public String getParentName() { 
     return parentName; 
    } 
    public void setParentName(String parentName) { 
     this.parentName = parentName; 
    } 

    @OneToMany(fetch=FetchType.LAZY, mappedBy="parent", cascade=CascadeType.ALL) 
    public List<Child> getChilds() { 
     return childs; 
    } 
    public void setChilds(List<Child> childs) { 
     this.childs = childs; 
    } 

} 

và lớp con tôi

package com.mazhar.beans; 

import static javax.persistence.GenerationType.IDENTITY; 

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

@Entity 
@Table(name = "child") 
public class Child { 
    private Integer idChild; 
    private String childName; 
    private Parent parent; //this actually we projected in criteria query. 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id_city", unique = true, nullable = false) 
    public Integer getIdChild() { 
     return idChild; 
    } 

    public void setIdChild(Integer idChild) { 
     this.idChild = idChild; 
    } 

    @Column(name = "city_name", nullable = false) 
    public String getChildName() { 
     return childName; 
    } 

    public void setChildName(String cName) { 
     this.childName = cName; 
    } 

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    @JoinColumn(name = "id_father") 
    public Parent getParent() { 
     return parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 
} 
0

Vấn đề chính của nhóm qua mà không có chiếu, theo cách bạn muốn, đó là trong một số DBMS như Oracle nó sẽ không làm việc, Oracle sẽ trả về một lỗi.

Nếu bạn nhóm một lựa chọn, bạn phải nhóm theo tất cả các trường không được tổng hợp mà bạn đang chọn. Ví dụ MySQL không có hạn chế này.

Cách tiếp cận mà tôi đang sử dụng chỉ chọn id làm phép chiếu nhómProperty với tất cả bộ lọc, thứ tự và số lượng giới hạn kết quả. Sau đó, thực hiện lọc truy vấn khác với các id được truy xuất này. Bằng cách đó, việc thực hiện sẽ độc lập với DBMS.

Các vấn đề liên quan