В текущем проекте пришлось сделать поисковый движок на коленке SQL-базе. Сейчас у меня есть такая схема:
<active_proxy_view>
id | entity | started at | expired at
<uuid> | <json> | <date> | <date>
<archive_proxy_view>
id | entity | started at | expired at
<uuid> | <json> | <date> | <date>
<metadata_reference>
entity_type | entity_id | metadata_key | metadata_value
proxy | <uuid> | visitors | 13
proxy | <uuid> | trial | yarr
<tracking_reference>
entity_type | entity_id | tracked_domain | tracked_type | tracked_id
proxy | <uuid> | campaign | carnival | halloween'16
Это все позволяет мне делать выборки следующего типа "найти все действующие прокси, соответствующие хэллоуину 16, начавшиеся после часа Х, у которых было по тринадцать посетителей и у которых был триальный доступ":
SELECT v.entity FROM active_proxy_view AS v
INNER JOIN metadata_reference AS m1
ON m1.entity_type = 'proxy' AND m1.entity_id = '?uuid'
AND m1.metadata_key = 'visitors' AND m1.metadata_value = '13'
INNER JOIN metadata_reference AS m2
ON m2.entity_type = 'proxy' AND m2.entity_id = '?uuid'
AND m2.metadata_key = 'trial' AND m2.metadata_value = 'yarr'
INNER JOIN tracking_reference AS t1
ON t1.entity_type = 'proxy' AND t1.entity_id = '?uuid'
AND t1.tracking_domain = 'campaign' AND t1.tracked_type = 'carnival'
AND t1.tracked_id = 'halloween\'16'
WHERE started_at > '?hourX'
so far so good. проблемы начинаются с текущим стэком, потому что все реализовано через spring и hibernate. В результате у меня получается, что записи из индекс-таблиц (tracking_reference, metadata_reference) имеют по две связанные записи во view-таблицах, а Hibernate при удалении записи из хотя бы одной таблицы удаляет связанные коллекции, обесточивая таким образом вторую таблицу. В данный момент это выглядит так:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class ProxyViewEntryTemplate {
...
@OneToMany(fetch = FetchType.LAZY, cascade = {})
@Cascade({})
@JoinColumn(name = MetadataRef.REFERENCE_ID_COLUMN_NAME)
@Where(clause = "entity_type = 'proxy'")
@SQLDeleteAll(sql = "DELETE FROM metadata_reference WHERE entity_id = ? and entity_type = 'proxy'")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private Collection<MetadataReference> metadata = new ArrayList<>();
И все равно даже с такими обвязками гибернейт норовит удалить мои записи из индекс-таблиц, а без указания @OneToMany я не могу обойтись, потому что иначе spring specification / criteria api не смогут работать с джойнами. Я могу спастись путем указания белиберды в @SQLDeleteAll (просто добавить WHERE 0 = 1), но это какой-то очень костыльный шаг. Есть ли нормальные способы запретить гибернейту удалять связанные сущности?