Оператор case HQL, возвращающий объект сущности

У меня есть таблица записей (для простоты я опустил сеттеры и другие атрибуты):

@Entity  
@Table(name="RECORD")  
public class Record {

    private long id;

    @Id
    @GeneratedValue
    @Column(name="ID") 
    public long getId() {
        return id;
    }
}

и таблица рекордных столкновений:

@Entity
@Table(name = "RECORD_COLLISION")
public class RecordCollision {

    private long id;

    private Record firstRecord;

    private Record secondRecord;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    public long getId() {
        return id;
    }

    @ManyToOne()
    @JoinColumn(name = "FIRST_RECORD")
    public Record getFirstRecord() {
        return firstRecord;
    }

    @ManyToOne()
    @JoinColumn(name = "SECOND_RECORD")
    public Record getSecondRecord() {
        return secondRecord;
    }
}

Мне нужно выбрать все записи, которые сталкиваются с указанной записью. Я попытался использовать этот запрос HQL:

SELECT CASE WHEN rc.firstRecord = :record THEN rc.secondRecord ELSE rc.firstRecord END 
    FROM RecordCollision rc 
    WHERE rc.firstRecord = :record OR rc.secondRecord = :record

Мне нужно использовать оператор CASE, потому что указанная запись может находиться в столбце firstRecord, и в этом случае мне нужно вернуть secondRecord, и наоборот.

Проблема в том, что после выполнения query.list() я получаю не список экземпляров Record, а список, содержащий один экземпляр Object. Кажется, что Hibernate не знает, что он должен возвращать результат оператора CASE как экземпляр Record. Как это сделать?


person Jardo    schedule 25.10.2013    source источник


Ответы (1)


Такой запрос JPQL/HQL можно написать без выбора регистра:

SELECT DISTINCT(r) FROM Record r 
WHERE 
r.id in (SELECT rc1.firstRecord.id 
         FROM RecordCollision rc1 
         WHERE rc1.secondRecord = :record) 
OR 
r.id in (SELECT rc2.secondRecord.id 
         FROM RecordCollision rc2 
         WHERE rc2.firstRecord = :record)

Если одно столкновение представлено только одной строкой, то DISTINCT не требуется.

person Mikko Maunu    schedule 26.01.2014
comment
Спасибо за вашу альтернативу, но не слишком ли неэффективно выполнение 2 подзапросов для этого? - person Jardo; 26.01.2014
comment
Производительность зависит, например, от оптимизатора запросов к базе данных и объема данных. Как это часто бывает, без измерений нельзя сказать, слишком ли это неэффективно. - person Mikko Maunu; 26.01.2014
comment
Было ли это достаточно хорошо, или вы нашли какое-то другое решение? - person Mikko Maunu; 05.04.2014
comment
При написании этого вопроса у меня уже было временное решение с использованием двух отдельных запросов и объединением результатов. Это временное решение, в конце концов, было запущено в производство и используется до сих пор (и, скорее всего, больше не будет изменено). Теперь у меня похожая проблема (поэтому я вернулся к этому вопросу), и я собираюсь использовать ваше решение. Хотя я думаю, что это не очень эффективно, но, вероятно, это лучше, чем выполнение двух отдельных запросов. - person Jardo; 16.12.2014