2017-10-05 96 views
0

比方说,我有一个实体,如聚集在休眠/ 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。

谢谢大家的答案,他们已经推动创造丑陋,但至少工作的解决方案。
我将不胜感激任何建议如何改善这种任务的代码。

+0

首先要求得到在条件查询相当于前纠正你的SQL查询;我不认为你可以在ID字段上聚合。 – ujulu

+0

是的,你是对的 - 这个查询是不正确的,它来自我的头顶只是为了这个例子 – user2256686

回答

0
createCriteria(Entity.class).add(Restrictions.in("name", new String[] {"foo","bar"})).add(Restrictions.eq("parameter","baz")).add(Projections.groupProperty("name")).add(Projections.groupProperty("id")).list() 

像这样的东西应该工作。你有什么尝试?

0
Criteria criteria = session.createCriteria(Entity.class,"entity"); 
criteria 
.add(Restrictions.in("name", new String[] {"foo","bar"})) 
.add(Restrictions.eq("parameter","baz")) 
.setProjection(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("id"), "id") 
.add(Projections.max("version")) 
.add(Projections.groupProperty("name")) 
.add(Projections.groupProperty("id")) 
.list(); 

我希望这个作品