比方说,我有一个实体,如聚集在休眠/ JPA
@Entity
@Table(name = "t_entity")
Entity {
@Id
@GeneratedValue
@Column(name = "id")
int id;
@Column(name = "name")
String name;
@Column(name = "version")
int version;
@Column(name = "parameter")
String parameter;
}
现在,我需要获取具有给定的名称和具体的参数值实体的最新版本。在普通的SQL我会写这样的事情:
select id, name, max(version) version, parameter
from entity
where name in ('foo', 'bar') and parameter = 'baz'
group by name, id
但是,我该怎么做与Hibernate(最好使用Criteria API)?
UPD:
首先,因为它是在注释中规定,我的例子查询是不正确。什么,我试图实现正确的版本看起来更像是这样的:
select e0.id, e0.name, e0.version, e0.parameter from entity e0
right join (select name, max(version) mv from entity where name in ('foo', 'bar') group by name) e1
on e0.name = e1.name and e0.versioin = e1.mv
where e0.parameter = 'baz'
我最好的工作版本,到目前为止涉及到两个独立的请求:
CriteriaBuilder cb = sessionFactory.getCriteriaBuilder();
CriteriaQuery<Tuple> lvq = cb.createQuery(Tuple.class);
Root<Entity> lvr = lvq.from(Entity.class);
lvq.multiselect(lvr.get("name").alias("name"), cb.max(lvr.get("version")).alias("mv"));
lvq.where(lvr.get("name").in("foo", "bar"));
lvq.groupBy(lvr.get("name"));
List<Tuple> lv = sessionFactory.getCurrentSession().createQuery(lvq).getResultList();
CriteriaQuery<Entity> cq = cb.createQuery(Entity.class);
Root<Entity> root = cq.from(Entity.class);
List<Predicate> lvp = new LinkedList<>();
for (Tuple tuple : lv) {
lvp.add(cb.and(
cb.equal(root.get("version"), tuple.get("mv")),
cb.equal(root.get("name"), tuple.get("name"))));
}
cq.select(root).where(cb.and(
cb.equal(root.get("parameter"),"baz"),
cb.or(lvp.toArray(new Predicate[lvp.size()])));
return sessionFactory.getCurrentSession().createQuery(cq).getResultList();
顺便说一下,可能是我没有足够的了解,其清晰Criteria API我想使用,所以它是JPA。
谢谢大家的答案,他们已经推动创造丑陋,但至少工作的解决方案。
我将不胜感激任何建议如何改善这种任务的代码。
首先要求得到在条件查询相当于前纠正你的SQL查询;我不认为你可以在ID字段上聚合。 – ujulu
是的,你是对的 - 这个查询是不正确的,它来自我的头顶只是为了这个例子 – user2256686