2013-07-02 3 views
2

Предоставлено 2 таблицыHibernate Критерии - Присоединение на ип отображенный объект

@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 будет генерировать следующие таблицы (уведомление я не объект для карты)

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

Я хочу использовать API Criteria, чтобы получить все экземпляры 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? Если да, как вы выполняете это соединение?

ответ

2

Прежде всего, начните с 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 непосредственно переводится на аналогичный критерии.

+0

Я думаю, что я собираюсь добавить двунаправленную связь. Я не изначально, потому что я не хотел, чтобы пользователи могли следить за этой ассоциацией. Я смотрел на другие вопросы, на которых вы даете тот же ответ, за исключением того, что в конце вы устанавливаете 'ResultTransformer'' DistinctRootEntityResultTransformer.INSTANCE'. Что это значит? –

+0

Кроме того, в первом варианте HQL выполняется ли объединение, как «естественное соединение», только отображение равных идентификаторов? –

+0

В результате он не может иметь одно и то же событие. Это в основном идентично наличию 'select distinct' в HQL. Возможно, вам это действительно понадобится. Забыл об этом. –

Смежные вопросы