Ответ 1
Я разрабатываю систему в Grails, которая интенсивно использует концепцию версии (как вы говорили выше). Мой подход был вторым в вашем вопросе.
Я создал два поля: internalVersion e disabled. Каждый класс, который должен быть Versionable, должен реализовать интерфейс с именем Versionable.
Я попробую объяснить здесь один из сценариев, необходимых для использования функциональности версии (простить мой английский).
Система, использующая эту концепцию, представляет собой коммерческую систему, в которой есть класс под названием Quote.
Каждая цитата может содержать одну или несколько версий, в которых действительна только последняя версия. Каждая цитата и ее версии создаются на основе переговоров с конкретным клиентом. Таким образом, клиент запрашивает у нас Цитату, и если по какой-то причине ему не нравятся цены (например), мы можем создать новую версию с некоторой скидкой. Каждая цитата имеет уникальный код, следующий текущей версией, например: QT-000022/0 (первая версия), QT-000022/1 (вторая версия).
Чтобы сгенерировать новую версию, я использую метод, который клонирует текущий объект (используя вид полного и глубокого сохранения как). Я копирую все (свойства и коллекции) в новый объект.
Метод clone определяет, что класс реализует интерфейс Versionable и выполняет следующие действия:
oldQuote.disabled = true
newQuote.internalVersion = oldQuote.internalVersion + 1
Таким образом, можно обеспечить включение только одной версии.
Надеюсь, вы понимаете мой подход.