Hibernate/JPA中的java聚合
假设我有一个实体,比如
@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();
顺便说一句,我可能不太清楚我想使用哪种标准API,所以是JPA
谢谢你们的回答,他们已经努力创造出丑陋但至少有效的解决方案
我将感谢任何关于如何改进此类任务代码的建议
# 1 楼答案
我希望这能奏效
# 2 楼答案
这样的办法应该行得通。你试过什么