给定2张桌子

@Entity
@Table
public class SomeEntity {
    @Id
    private Long someId;

    @Column
    private String text;

    @ManyToMany
    @JoinTable(name = "map", joinColumns = @JoinColumn(name = "someId"), inverseJoinColumns = @JoinColumn(name = "eventId"))
    private Set<SomeEntityEvent> events;

    // get/set
}




@Entity
@Table
public class SomeEntityEvent {
    @Id
    private Long eventId;

    @Column
    private Calendar date;

    // get/set
}


Hibernate将生成以下表格(注意,我没有Map的实体)


some_entity: someId | text
some_entity_event: eventId | date
map: someId | eventId



我想使用Criteria API来获取属于某个SomeEntityEvent的所有SomeEntity实例,这些实例按日期排序并且在一定范围内。使用SQL,我可以轻松完成

SELECT *
FROM some_entity_event e
NATURAL JOIN map
WHERE map.someId = [ my field ]
ORDER BY e.date DESC
LIMIT 0, 100;


由于我没有Map实体(或对SomeEntity的引用),因此我不知道如何构建与上述查询等效的Criteria。以下条件使我全都SomeEntityEvent。我只想要属于某些SomeEntity的那些。

Criteria criteria = getCurrentSession().createCriteria(SomeEntityEvent.class);
criteria.addOrder(Order.desc("date"))
    .setFirstResult(firstResult)
    .setMaxResults(maxResults);
return criteria.list();


Criteria可以吗?如果是,您如何执行该加入?

最佳答案

首先,从HQL开始。当必须基于一组...条件来动态组成查询时,条件很有用。即使您绝对要使用条件API,使用HQL查询并进行翻译也更加容易。

好的,因此您希望属于某个SomeEntity的事件按日期在一定范围内排序:

select event from SomeEntity entity
join entity.events event
where entity.id = :entityId
and event.date between :startDate and :endDate
order by event.date


现在,您可以将其转换为条件。问题在于标准API不允许选择除根实体之外的任何其他实体,并且由于您没有从SomeEntityEvent到SomeEntity的关联,因此您会陷入困境。

因此,我的建议是:在HQL中执行此操作,或者将关联设为双向。如果是双向的,则可以这样编写HQL查询:

select event from SomeEntityEvent event
join event.entities entity
where entity.id = :entityId
and event.date between :startDate and :endDate
order by event.date


它可以轻松地转换为标准:

Criteria c = session.createCriteria(SomeEntityEvent.class, "event");
c.createAlias("event.entities", "entity");
c.add(Restrictions.eq("entity.id", entityId);
c.add(Restrictions.between("event.date", startDate, endDate);
c.addOrder("event.date");


请注意,HQL查询的每个部分如何直接转换为类似的条件指令。

09-27 22:37