我有一个Criteria- query,它连接第二个表B,从表A中选择实体。问题是,这个查询多次返回表A中的一些实体。但我需要的结果是不同的。
使用Criteria.DISTINCT_ROOT_ENTITY是没有用的,因为这会在执行SQL查询后过滤掉多次出现的情况。因此,当我将我的结果限制为20个匹配时,我最终只得到了4个,尽管有更多的条目,匹配我的查询。
在纯SQL中,我可以简单地将"GROUP BY ID“添加到查询中,一切都很好,因为表B的连接仅用于选择表A中的实体。但是使用Criteria-API我无法做到这一点。添加"GROUP BY“的唯一方法是使用投影。但是,我最终得到了标量值,而不是我的类的一个真正的实例。使用SQL限制也不起作用,因为hibernate在我的"GROUP BY"-clause后面添加了一个虚假的"1=1“。:(
有什么想法吗?
发布于 2011-11-30 02:07:15
你有没有试过用这样的东西?
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();您可以通过类的反射动态添加属性。
这将创建如下的SQl:select distinct prop1,prop2,prop3,prop4 from yourClass
我没有包括DetachedCriteria dc,因为它无关紧要。
发布于 2013-09-25 15:11:18
没有投影的bean分组:是不可能的,因为它是有意义的,在许多答案中你可能会发现,但大多数人不想使用投影,因为它要求他们投影每个属性,但要求必须投影一个。(并作为结果返回)。在下面的示例中,我尝试将所需的bean作为结果对象进行project。
我用了一点小技巧也达到了同样的效果,我相信,首先我试图在没有投影的情况下应用group by,但我没有找到解决方案,所以我只能依靠投影。
以下是我想要实现的目标
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在Java代码中,我希望p.*是一个Parent类,它是我的实体bean,并且我希望它是唯一的,一种方法是在一个集合中获取结果列表,但由于许多原因,我不喜欢这种方式:)
因此,我从Child.class而不是Parent.class创建了一个条件,这个技巧对我很有效。
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);
}如果您还不明白,这里是我的映射实体Bean类。
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;
}
}我的孩子班级
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;
}
}发布于 2010-01-11 19:18:28
可以编写Hibernate可以用来返回实体的实际SQL查询。所以如果你真的需要的话,你可以绕过HQL,在GROUP BY中精确地编写你想要的查询。
详情请参见here。
例如,您可以在hbm.xml文件中定义如下查询:
<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>请注意用于选择实体X和实体Y的所有属性的{x.}和{y.}速记语法
https://stackoverflow.com/questions/2035359
复制相似问题