Использование составного главного ключа в JPA

Имеется: таблица с двумя колонками: одна содержит простые данные (INT), вторая - вторичный ключ, представленный INT-ом. Основным является составной ключ из двух колонок. Код создания:

CREATE TABLE data_foreignKey
(
    data INT,
    foreignKey INT,
    CONSTRAINT data_foreignKey_pk
        PRIMARY KEY (data , foreignKey )
);

В коде создан entity, соответствующий таблице:

@Entity
@Table(name = "data_foreignKey")
@IdClass(DataForeignKeyCompositeKey.class)  // См. ниже
public class DataForeignKey{
    @Id  // См. ниже
    @Column(name = "data")
    private Integer data;

    @Id  // См. ниже
    @JoinColumn(name = "foreignKey")
    @ManyToOne(fetch = FetchType.LAZY)
    private ForeignType foreign;

    // ...
}

Класс ForeignType:

@Entity
@Table(name = "foreignTypes")
public class ForeignType {
    @Id
    @Column(name = "id")
    private Integer id;

    ...
}

Была попытка прикрутить составной ключ с использованием @IdClass: в классе DataForeignKey появились аннотации, отмеченные комментариями, а также был создан следующий класс:

public class DataForeignKeyCompositeKey implements Serializable {
    private Integer data;
    private ForeignType foreign;
}

Программа скомпилировалась, однако при попытке записать в БД объект DataForeignKey Spring выдал мне ошибку следующего содержания: java.lang.IllegalArgumentException: Can not set o.C.ForeignType field o.C.DataForeignKeyCompositeKey.foreign to java.lang.Integer.

Я прошёлся отладчиком, и перед вызовом условного dataForeignKeyRepository.saveAndFlush(dataForeignKey) переменная dataForeignKey содержит правильный набор данных (то есть, dataForeignKey.foreign != null).

Вопрос: Что могло пойти не так? Можно ли воспользоваться @IdClass для решения такой задачи?


Ответы (1 шт):

Автор решения: Roman Konoval

Поле foreign в DataForeignKeyCompositeKey должно быть Integer, т.е. это должен быть ключ из ForeignType, а не сама сущность:

public class DataForeignKeyCompositeKey implements Serializable {
    private Integer data;
    private Integer foreign;
}

Тут есть пример.

→ Ссылка