Я надеюсь, что кто-то будет достаточно любезен, чтобы дать несколько советов относительно того, как наилучшим образом подойти к следующей проблеме.Полиморфное сопоставление с аннотациями гибернации
Я пытаюсь использовать Hibernate с аннотациями для создания общей библиотеки отображаемых суперклассов, которые могут использоваться из клиентских приложений путем расширения общих объектов. Имена таблиц базы данных, используемые всеми клиентскими приложениями, одинаковы, хотя столбцы конкретных приложений могут присутствовать в дополнение к общим столбцам, отображаемым в общих сопоставлениях.
Вот пример. 5 разных приложений имеют общий код UserLogon. Итак, в общей библиотеке класс может выглядеть так:
@Entity
@Table(name="DRY_USER_LOGON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula("666") // A trick - any subclass mapped with @DiscriminatorValue("666") found on the classpath will be used!
public abstract class CommonUserLogon {
@Id
@Column(name = "USER_LOGON_OID")
Long oid;
@Column(name = "USER_LOGON_NAME")
String userLogonName;
@OneToOne(mappedBy="userLogon")
CommonUserProfile userProfile;
... etc ...
}
@Entity
@Table(name="DRY_USER_PROFILE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula("666") // A trick - any subclass mapped with @DiscriminatorValue("666") found on the classpath will be used!
public abstract class CommonUserProfile {
@Id
@Column(name = "USER_PROFILE_OID")
Long oid;
// Hibernate will use the subclass that matches the discriminator at runtime, which is great
@ManyToOne
@JoinColumn(name = "USER_LOGON_OID")
CommonUserLogon userLogon;
... etc ...
}
Этот подход работает очень хорошо. Все, что я должен сделать в своих клиентских приложениях что-то вроде:
@Entity
@DiscriminatorValue("666") // Has to match @DiscriminatorFormula in superclass
public class UserLogon extends CommonUserLogon {
@OneToMany(mappedBy="userLogon")
Set <ClientSpecificStuff> clientExtensions;
.. etc ..
}
@Entity
@DiscriminatorValue("666") // Has to match @DiscriminatorFormula in superclass
public class UserProfile extends CommonUserProfile {
/**
* @return Cast to program-specific UserLogon
*/
public UserLogon getUserLogon() {
(UserLogon)super.getUserLogon();
}
@Column(name = "APP_SPECIFIC_COL1")
String appSpecificThing;
... etc ...
}
Мне нравится этот подход, б/с Я был в состоянии повторно использовать все общие отображения, и я не должен повторяться в любом месте.
Теперь о проблеме. Предположим, что я хочу создать еще один общий компонент, который добавляет что-то к CommonUserLogon
.
// ????? - How to map this?
public abstract class CommonUserLogonWithDigitalSignature extends CommonUserLogon {
@OneToMany(mappedBy="userLogon")
List<UserKeyPair> userKeyPairs;
... etc ...
}
@Entity
@Table(name="DRY_USER_SECURITY_KEY")
public class UserKeyPair {
@Id
@Column(name = "USER_SECURITY_KEY_OID")
Long oid;
@ManyToOne
@JoinColumn(name = "USER_LOGON_OID", nullable = false)
CommonUserLogonWithDigitalSignature userLogon;
... etc ...
}
Теперь у нас есть более чем на один уровень подклассов, то DiscriminatorFormula
подход не очень удобен больше, б/с становится трудно контролировать, какие конкретные подклассы загружаются во время выполнения. Он по-прежнему работает в принципе, если есть ТОЧНО один подкласс с по пути к классам, но это непросто сделать во время тестирования, где мы можем протестировать оба подкласса: и CommonUserLogon
.
Итак, в этот момент я хотел остановиться и убедиться, что я нахожусь на правильном пути, или, может быть, есть лучший способ сделать то, что я описал?
Любые советы были бы весьма полезными.