HQL оставил внешнее соединение с отсутствующим отображением
Я использую hibernate/hql для создания моих запросов. Теперь у меня есть проблема, на которой я застрял уже несколько часов, чтобы понять ситуацию, вот мое окружение:
Я получил 3 таблицы, из которых мне нужно получить информацию, с таблицами соединений / назначений, которые я получил в общей сложности 5. Информация, которая мне нужна, это Key, Type и SourceFile, но особый случай здесь заключается в том, что sql будет выполнен при импорте новых данных, поэтому я хочу сначала проверить, существуют ли данные уже или частично. Мой запрос должен всегда давать мне ключ, независимо от того, какой тип или SourceFile, если сам ключ уже находится в базе данных, и тогда мне нужен только ключ, а не другая информация. (Ключ совпадает, но SourceFile и Type нет, поэтому я хочу вернуть только ключ). Если ключ существует с точно таким же типом и SourceFile, я хочу получить всю информацию.
Таблицы являются:
(заголовок: FK_K_ID сохраняется как объект с ключом имени, FK_S_ID сохраняется как источник, а FK_T_ID сохраняется как тип)
Ключ:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| K_ID | bigint(20) | NO | PRI | NULL | auto_increment |
| key | varchar(255) | NO | | NULL | |
| deleted | boolean | NO | | FALSE | |
+-------------+--------------+------+-----+---------+----------------+
KeyType:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| KT_ID | bigint(20) | NO | PRI | NULL | auto_increment |
| FK_K_ID | bigint(20) | NO | | NULL | |
| FK_T_ID | bigint(20) | NO | | NULL | |
| deleted | boolean | NO | | FALSE | |
+-------------+--------------+------+-----+---------+----------------+
Тип:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| T_ID | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| description | varchar(255) | NO | | NULL | |
| deleted | boolean | NO | | FALSE | |
+-------------+--------------+------+-----+---------+----------------+
KeySource:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| KS_ID | bigint(20) | NO | PRI | NULL | auto_increment |
| FK_K_ID | bigint(20) | NO | | NULL | |
| FK_S_ID | bigint(20) | NO | | NULL | |
| deleted | boolean | NO | | FALSE | |
+-------------+--------------+------+-----+---------+----------------+
Источник:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| S_ID | bigint(20) | NO | PRI | NULL | auto_increment |
| sourceFile | varchar(255) | NO | | NULL | |
| deleted | boolean | NO | | FALSE | |
+-------------+--------------+------+-----+---------+----------------+
и вот что я попробовал до сих пор:
from KeyType kt
right outer join kt.Key k
with k.name in (...)
where k.deleted = false
and ( kt.Type in (...) or kt is null )
Проблема с этим в том, что он делает то, что я хочу. но я получаю все ключи в базе данных и KeyType только там, где они совпадают, иначе ноль. Я не хочу получать все ключи, я просто хочу получить мои ключи, которые я просил.
from KeyType kt
right outer join kt.Key k
with k.name in (...)
where k.deleted = false
and (k.name in (...) and kt.Type in (...) or kt is null )
Я даже не знаю, что я пытался здесь сказать честно. Я думаю, я пытался оптимизировать первый запрос, чтобы дать только те ключи, которые я просил.
from KeyType kt
right outer join fetch kt.Key k
where k.deleted = false
and (k.name in (...) and kt.Type in (...) or kt is null )
Я также пытался использовать fetch как этот или в других вариантах, но не работал так, как мне нужно.
from Key k
left outer join KeyType kt on kt.Key.id = k.id
left outer join KeySource ks on ks.Key.id = k.id
inner join Source s on ks.Source.id = s.id
where k.deleted = false
and k.name in (...)
and ( kt.appType in (...) or kt is null )
and ( s.SourceFile in (...) or s is null )
хорошо, как и ожидалось, это не работает. Я имею в виду, что очень просто увидеть, что это не может работать, но вы стараетесь изо всех сил, если не можете с этим справиться.
Я перепробовал еще много комбинаций и вариантов запросов, но безуспешно. Первый запрос - самый близкий, который я получил. Надеюсь, кто-нибудь сможет мне помочь.
PS: я не могу изменить отображение или сущности сейчас. Я должен работать с тем, что я получил.
ОБНОВИТЬ:
Хорошо, поэтому я очень близок к решению проблемы. Мой запрос теперь выглядит так:
select k, case when kt.Type not in (...) then null
else 1 end
from KeyType kt
join kt.Key k
where k.name in (...)
Теперь единственное, что я хочу, - это обмен 1 с реальным объектом. Но если я делаю это, я получаю сообщение об ошибке "org.hibernate.exception.GenericJDBCException: не удалось выполнить запрос" (работает на оракуле БД)
Может кто-нибудь сказать мне, как это решить?
1 ответ
Для моего случая и окружения так, как я хотел, это невозможно.
Поэтому я снова спросил коллег, и мы пришли к решению, что мы должны сделать это за один запрос.
Просто говорю это для тех, кто проходит мимо этого поста с той же конфигурацией / проблемой таблицы.