Мне очень интересна эта тема. Я работаю уже несколько лет в разработке приложений, использующих эти шаблоны, в нашем случае идея возникла из дипломной работы на немецком языке.
Я не знал фреймворков "DAO Fusion", они предоставляют интересную информацию и ссылки, спасибо за предоставление этой информации. Особенно замечательны страницы шаблона и страницы аспектов !
На ваши вопросы: нет, я не могу указать на другие сайты, примеры или рамки. Я боюсь, что вам придется использовать либо инфраструктуру DAO Fusion, либо реализовать эту функцию самостоятельно. Вы должны различать, какая функциональность вам действительно нужна. Чтобы говорить с точки зрения структуры «DAO Fusion»: вам нужны как «действительный временной», так и «рекордный временной»? Записывайте временные состояния, когда изменения применяются к вашей базе данных (обычно используются для проверки проблем), действительные временные состояния, когда изменения произошли в реальной жизни или действительны в реальной жизни (используемые приложением), которые могут отличаться от временных записей. В большинстве случаев достаточно одного измерения, а второе не требуется.
В любом случае, временная функциональность влияет на вашу базу данных. Как вы заявили: «которые теперь их первичные ключи включают в себя срок действия» . Итак, как вы моделируете личность сущности? Я предпочитаю использовать суррогатные ключи . В этом случае это означает:
- один идентификатор для сущности
- один идентификатор для объекта в базе данных (строка)
- временные столбцы
Первичным ключом для таблицы является идентификатор объекта. Каждый объект имеет одну или несколько (1-n) записей в таблице, идентифицируемых идентификатором объекта. Связывание между таблицами основано на идентификаторе сущности. Поскольку временные записи умножают объем данных, стандартные отношения не работают. Стандартное отношение 1-n может стать отношением x * 1-y * n.
Как вы решаете это? Стандартный подход состоит в том, чтобы ввести таблицу сопоставления, но это не естественный подход. Просто для редактирования одной таблицы (например, происходит смена места жительства) вам также придется обновить / вставить таблицу отображения, что странно для каждого программиста.
Другой подход заключается в том, чтобы не использовать таблицу сопоставления. В этом случае вы не можете использовать ссылочную целостность и внешние ключи, каждая таблица действует изолированно, связь из одной таблицы с другой должна быть реализована вручную, а не с помощью функций JPA.
Функциональность инициализации объектов базы данных должна находиться внутри объектов (как в платформе DAO Fusion). Я бы не стал ставить это на службу. Если вы отдаете его в DAO или используете шаблон Active Record, выбор за вами.
Мне известно, что в моем ответе нет готовой к использованию инфраструктуры. Вы находитесь в очень сложной области, от ресурсов моего опыта до этого сценария использования очень трудно найти. Спасибо за ваш вопрос! Но в любом случае я надеюсь, что помог вам в вашем дизайне.
В этом ответе вы найдете справочник «Разработка ориентированных на время приложений баз данных в SQL», см. https://stackoverflow.com/a/800516/734687
Обновление: пример
- Вопрос: Допустим, у меня есть таблица PERSON, у которой есть суррогатный ключ, который является полем с именем "id". Каждая ссылочная таблица в этот момент будет иметь этот «идентификатор» в качестве ограничения внешнего ключа. Если я добавлю временные столбцы, я должен изменить первичный ключ на «id + from_date + to_date». Перед изменением первичного ключа мне нужно было бы сначала отбросить все внешние ограничения каждой ссылочной таблицы в эту ссылочную таблицу (Person). Я прав? Я полагаю, что вы имеете в виду суррогатный ключ. ID - это сгенерированный ключ, который может быть сгенерирован последовательностью. Бизнес-ключ таблицы Person - это SSN.
- Ответ: Не совсем. SSN будет естественным ключом, который я не использую для идентификации личности. Также "id + from_date + to_date" будет составным ключом , которого я также избегал бы. Если вы посмотрите на пример , у вас будет две таблицы: человек и место жительства, и в нашем примере мы скажем, что у нас есть отношение 1-n с местом жительства с внешним ключом.
Теперь мы добавляем временные поля на каждую таблицу. Да, мы отбрасываем все ограничения внешнего ключа. Человек получит 2 идентификатора, один идентификатор для идентификации строки (назовите его ROW_ID), один идентификатор для идентификации самого человека (назовите его ENTIDY_ID) с индексом на этом идентификаторе. То же самое для человека. Конечно, ваш подход тоже будет работать, но в этом случае у вас будут операции, которые изменяют ROW_ID (при закрытии временного интервала), которого я бы избегал.
Чтобы расширить пример , реализованный с учетом предположений выше (2 таблицы, 1-n):
запрос, чтобы показать все записи в базе данных (вся информация о достоверности и запись - в том числе техническая - информация включена):
SELECT * FROM Person p, Residence r
WHERE p.ENTITY_ID = r.FK_ENTITY_ID_PERSON // JOIN
запрос на скрытие записи - он же технический - информация. Здесь показаны все действительные изменения сущностей.
SELECT * FROM Person p, Residence r
WHERE p.ENTITY_ID = r.FK_ENTITY_ID_PERSON AND
p.recordTo=[infinity] and r.recordTo=[infinity] // only current technical state
запрос для отображения фактических значений.
SELECT * FROM Person p, Residence r
WHERE p.ENTITY_ID = r.FK_ENTITY_ID_PERSON AND
p.recordTo=[infinity] and r.recordTo=[infinity] AND
p.validFrom <= [now] AND p.validTo > [now] AND // only current valid state person
r.validFrom <= [now] AND r.validTo > [now] // only current valid state residence
Как видите, я никогда не использую ROW_ID. Замените [сейчас] временной меткой, чтобы вернуться во времени.
Обновление для отражения вашего обновления
Я бы порекомендовал следующую модель данных:
Введите таблицу «PlaysInTeam»:
- ID
- ID команды (внешний ключ к команде)
- ID игрока (внешний ключ к игроку)
- ValidFrom
- ValidTo
Когда вы перечисляете игроков команды, вы должны запросить дату, для которой отношения действительны и должны быть в [ValdFrom, ValidTo)
Для того, чтобы сделать команду временной, у меня есть два подхода;
Подход 1:
Введите таблицу "Сезон", которая моделирует срок действия для сезона
- ID
- Название сезона (например, лето 2011)
- С (может быть, не обязательно, потому что каждый знает, когда сезон)
- Кому (может быть, и не нужно, потому что каждый знает, когда наступит сезон)
Разделить командный стол. У вас будут поля, принадлежащие команде и не имеющие отношения ко времени (имя, адрес, ...) и поля, относящиеся ко времени для сезона (победа, поражение, ..). В этом случае я бы использовал Team и TeamInSeason. PlaysInTeam может ссылаться на TeamInSeason вместо Team (необходимо учитывать - я бы позволил указать на Team)
TeamInSeason
- ID
- ID Team
- ID Сезон
- Win
- Потеря
- ...
Подход 2:
Не моделируйте сезон явно. Разделите командный стол. У вас будут поля, принадлежащие команде и не имеющие отношения ко времени (имя, адрес, ...) и поля, которые относятся ко времени (победа, поражение, ..). В этом случае я бы использовал Team и TeamInterval. TeamInterval будет иметь поля «от» и «до» для интервала. PlaysInTeam может связываться с TeamInterval вместо Team (я бы позволил это в Team)
TeamInterval
- ID
- ID Team
- С
- К
- Win
- Потеря
- ...
В обоих подходах: если вам не нужна отдельная командная таблица для не относящегося ко времени поля, не разбивайте.