Какое хорошее решение для связывания разных таблиц в Hibernate на основе некоторого значения поля?

У меня есть таблица article и несколько пользовательских таблиц a_user, b_user,... с точно такой же структурой (но разными данными). Я не могу ничего изменить в таблицах *_user, кроме префикса имени таблицы, но могу изменить все остальное (пользовательские таблицы содержат только информацию о пользователе, в них нет ничего о article или user_type).

Мне нужно связать статью с пользователем (многие к одному), но имя пользовательской таблицы определяется полем user_type. Например

Article table record:
...
user_id="5"
user_type="a"

означает, что он связан с пользователем с id=5 из таблицы a_user (id 5 не уникален в области пользователей, каждая пользовательская таблица может иметь свой id 5).

Любые предложения, как справиться с этой ситуацией? Как я могу сопоставить это отношение в Hibernate (сопоставление XML, без аннотаций), чтобы оно автоматически выбирало правильного пользователя для статьи во время выбора/обновления? Как мне сопоставить пользовательские таблицы (один или несколько классов?)?

Мне нужно будет выполнить несколько запросов, подобных этому:

from Article a where a.userType=:type and a.user.name=:name

Спасибо.


person serg    schedule 27.05.2010    source источник
comment
Довольно странный дизайн базы данных, как определяется внешний ключ для статьи таблицы?   -  person tkr    schedule 27.05.2010
comment
Ну, в настоящее время это не определено. Раньше это было простое отношение «многие к одному» с одной пользовательской таблицей. Теперь это должно быть несколько пользовательских таблиц. Почему пользовательских таблиц несколько - они идут из другого продукта (форума), а у нас несколько форумов.   -  person serg    schedule 27.05.2010


Ответы (1)


Hibernate имеет аннотацию @Any (и элемент <any> xml) для таких дизайнов.

Извините за аннотации, но я не силен в hbm.xml. Его можно перевести в XML, см. <any> элемент:

@Entity @Table(name = "Article")
public class Article {

    @Any(metaColumn = @Column(name = "user_type"))
    @AnyMetaDef(
            idType = "integer",
            metaType = "string",
            metaValues = {
                    @MetaValue(value = "A", targetEntity = UserA.class),
                    @MetaValue(value = "B", targetEntity = UserB.class)
            }
    )
    @JoinColumn(name = "user_id")
    private User user;

    ...
}

UserA и UserB используют одну и ту же схему, определенную User:

@MappedSuperclass
abstract public class User {
    @Id
    private Long id;

    private String name;

    ...
}

@Entity @Table(name = "a_user")
public class UserA extends User {}

@Entity @Table(name = "b_user")
public class UserB extends User {}
person axtavt    schedule 27.05.2010
comment
Спасибо, похоже, это именно то, что мне нужно. - person serg; 28.05.2010