#hibernate #spring-data-jpa #composite-primary-key
Вопрос:
У меня есть несколько сущностей:
@Entity
@Table(name = "cbonus")
public class BonusEntity {
@EmbeddedId
@AttributeOverride(name = "id", column = @Column(name = "id"))
@AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id"))
private BonusId bonusId;
private boolean released;
@ManyToOne(targetEntity = AccountEntity.class, optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", insertable = false, updatable = false)
@JoinColumn(name = "bank_id", referencedColumnName = "bank_id", insertable = false, updatable = false)
@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable = false, updatable = false)
private AccountEntity account;
}
@Entity
@Table(name = "account")
public class AccountEntity {
@EmbeddedId
@AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id"))
@AttributeOverride(name = "bankId", column = @Column(name = "bank_id"))
@AttributeOverride(name = "userId", column = @Column(name = "user_id"))
@NotNull
private AccountId accountId;
// other fields
}
Когда я пытаюсь сохранить новую запись cbonus, у меня есть исключение:
org.postgresql.util.Исключение PSQLException: ОШИБКА: значение null в столбце «bank_id» отношения «cbonus» нарушает ограничение not-null Подробно: Неудачная строка содержит (773, gp3, null, null, f).
и запрос
ОТЛАДКА 24817 — [nio-8080-exec-4] org.hibernate.SQL
: вставка в значения cbonus (выпущено, идентификатор кластера, идентификатор) (?, ?, ?)
Непосредственно перед сохранением в объекте заполнены все поля. Я попытался удалить ограничения на нулевое значение, но тогда значения просто останутся НУЛЕВЫМИ. Я думаю, что причина в наложении составного первичного ключа и составного внешнего ключа.
Как я могу справиться с этим с помощью Hibernate?
схемы бд:
CREATE TABLE cbonus
(
id BIGINT NOT NULL,
cluster_id TEXT NOT NULL,
bank_id BIGINT NOT NULL,
user_id TEXT NOT NULL,
released BOOLEAN DEFAULT FALSE NOT NULL,
FOREIGN KEY (cluster_id, bank_id, user_id) REFERENCES account,
PRIMARY KEY (id, cluster_id)
);
CREATE TABLE account
(
cluster_id TEXT NOT NULL,
bank_id BIGINT NOT NULL,
user_id TEXT NOT NULL,
-- [other fields]
PRIMARY KEY (cluster_id, bank_id, user_id)
);
Ответ №1:
Ваше отображение неверно. Столбец bank_id никогда не будет «доступен для записи» в соответствии с вашими настройками. Тебе это нужно:
@AttributeOverride(name = "id", column = @Column(name = "id"))
@AttributeOverride(name = "clusterId", column = @Column(name = "pk_cluster_id"))
private BonusId bonusId;
@ManyToOne(targetEntity = AccountEntity.class, optional = false, fetch = FetchType.LAZY)
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(column = @JoinColumn(name = "bank_id", referencedColumnName = "bank_id")),
@JoinColumnOrFormula(column = @JoinColumn(name = "user_id", referencedColumnName = "user_id")),
@JoinColumnOrFormula(formula = @JoinFormula(value = "cluster_id", referencedColumnName = "cluster_id"))
private AccountEntity account;
})
и некоторое исправление схемы:
CREATE TABLE command_response
(
id BIGSERIAL PRIMARY KEY,
pk_cluster_id TEXT NOT NULL,
cluster_id TEXT NOT NULL,
bank_id BIGINT NOT NULL,
...
FOREIGN KEY (cluster_id, bank_id, user_id) REFERENCES account,
PRIMARY KEY (id, pk_cluster_id)
Комментарии:
1. Спасибо, ты был отчасти прав. Кроме того, мы должны разделить перекрывающиеся компоненты primary_keys по разным столбцам.