Hibernate аннотации: многие ко многим с общим атрибутом составного ключа - PullRequest
1 голос
/ 08 ноября 2019

Я пытаюсь отобразить существующую схему базы данных, используя аннотации Hibernate + JPA.

Одна из моих сущностей отображается так:

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    private int department;

    @Id
    private int userId;

    ...

И другая сущность, группа:

@Entity
@Table(name = "groups")
public class Group implements Serializable {

    @Id
    private int department;

    @Id
    private int groupId;

    ...

Группа и пользователь должны иметь отношение «многие ко многим» между ними, но проблема в том, что в таблице соединения («user_group») есть только столбцы «DEPARTMENT, USERID, GROUPID» - т.е. Столбец DEPARTMENT необходимо использовать как в joinColumns, так и в inverseJoinColumns:

    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "user_groups",
        joinColumns = { @JoinColumn(name = "department"), @JoinColumn(name = "groupid") },
        inverseJoinColumns = {@JoinColumn(name = "department"), @JoinColumn(name = "userid") }
    )
    private List<User> groupUsers = new ArrayList<>();

, что приводит к ошибке сопоставления - «Повторяющийся столбец в сопоставлении для сущности».

Однако похоже, что это было /возможно с использованием XML, потому что этот точный пример существует в старой документации Hibernate. Но я не могу найти никаких доказательств того, что это когда-либо работало с использованием аннотаций? Я попытался с @JoinFormula вместо @JoinColumn, но это не компилируется. Возможно ли это?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Хорошо, я почти уверен, что это невозможно.

Я нашел многообещающее решение:

Создайте @Embeddable для таблицы "user_group":


@Embeddable
public class UserGroupMembership implements Serializable {

    @ManyToOne
    @JoinColumnsOrFormulas(
        value = {
            @JoinColumnOrFormula(column = @JoinColumn(referencedColumnName = "userid", name = "userid")),
            @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "department", value = "department"))
        })
    private User user;

    public UserGroupMembership(User user) {
        this.user = user;
    }

    public UserGroupMembership() {
    }

    public User getUser() {
        return user;
    }
}

Хитрость в том, что @ManyToOne позволяет вам использовать @JoinColumnsOrFormulas, поэтому одним из условий соединения может быть формула, которая, как мне кажется, не работает для @ManyToMany (аннотация @JoinColumnsOrFormulas игнорируется, поскольку она ожидает столбцы соединениябыть частью аннотации @JoinTable).

Затем UserGroupMemberships отображаются как ElementCollection:

    @ElementCollection
    @CollectionTable(name = "user_group", joinColumns = {
        @JoinColumn(name = "department", referencedColumnName = "department"),
        @JoinColumn(name = "groupid", referencedColumnName = "groupid")
    })
    @OrderColumn(name = "seq", nullable = false)
    private List<UserGroupMemberships> groupUsers = new ArrayList<>();

Это работает только сейчас для однонаправленного отношения «многие ко многим».

0 голосов
/ 08 ноября 2019

Я думаю, что они изменили имя идентификатора на EmbeddedId вместо CompositeId. Если вы сделаете составной идентификатор, как это;вы можете напрямую использовать ключ для обратного отображения;

Этот фрагмент основан на Hibernate версии 5.2.18.Final .

@Embeddable
public class UserPK implements Serializable {

    private int department;

    private int userId; 

    public UserPK() {}

    public UserPK(int department, int userId) {
        this.department= department;
        this.userId= userId;
    }

    // Override equals() and hashCode()
}

Класс сущности использует ключ, подобный этому;

@Entity(name = "users")
public class User implements Serializable {

    @EmbeddedId
    private UserPK userKey;

    ...

И то же самое изменение класса вашей группы;

@Embeddable
public class GroupPK implements Serializable {

    private int department;

    private int groupId; 

    public GroupPK() {}

    public GroupPK(int department, int groupId) {
        this.department= department;
        this.groupId= groupId;
    }

    // Override equals() and hashCode()
}

@Entity(name = "groups")
public class Group implements Serializable {

    @EmbeddedId
    private GroupPK groupKey

    ...

Чтобы присоединиться к таблице, теперь можно использовать EmbeddedId ссылочное имя;

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
    name = "user_groups",
    joinColumns = { @JoinColumn(name = "userKey") },
    inverseJoinColumns = {@JoinColumn(name = "groupKey")}
)
private List<User> groupUsers = new ArrayList<>();

Вы можете иметь большеинформация из этого документа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...