У меня есть следующий «Родитель»:
@Entity
@Table(name = "messages")
@SequenceGenerator(name = "messageSequence", sequenceName = "message_sequence")
public class Message {
@Id
@Column(name = "message_id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "messageSequence")
Long messageId;
@OneToMany(mappedBy = "message", cascade=CascadeType.ALL)
List<Recipient> recipients = new ArrayList<>();
public void addRecipient(Recipient r) {
r.setMessage(this);
recipients.add(r);
}
@Column(name = "message_body")
String body;
// Constructors/Getters/Setters
...
}
И получатель «Дочерний»:
@Entity
@Table(name = "message_recipients")
public class Recipient {
@EmbeddedId
private RecipientId recipientId;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "message_id")
private Message message;
public void setMessage(Message msg) {
this.message = msg;
}
public Recipient(Message msg, String name) {
this.id = new RecipientId(msg, name);
this.message = msg;
}
@Override
public boolean equals(Object o) { ... }
@Override
public int hashCode(Object o) { return key.hashCode(); }
}
С составным ключом:
@Embeddable
public class RecipientId implements Serializable {
@Column(name = "message_id")
Long messageId;
@Column(name = "message_to")
String messageTo;
@Column(name = "message_timestamp")
LocalDateTime messageTimestamp;
public RecipientId(Message msg, String messageTo) {
this.messageId = msg.messageId;
this.messageTo = messageTo;
this.messageTimestamp = LocalDateTime.now();
}
@Override
public boolean equals(Object o) { ... }
@Override
public int hashCode() {
return Objects.hash(messageId, messageTo, messageTimestamp);
}
}
У меня есть следующий тестовый код:
@Bean
public void makeMessage(MessageRepository messages) {
Message newMsg = new Message();
newMsg.addRecipient(new Recipient(newMsg, "recipientName"));
newMsg.setBody("This is a test message");
messages.save(newMsg);
}
При выполнении makeMessage () я вижу в выходных данных отладки, что Message получает сгенерированное значение MessageId, но при сохранении получателей messageId составного ключа имеет значение null,вызывая сбой транзакции.
2018-11-27 14:49:54.158 DEBUG 2791 --- [ restartedMain] org.hibernate.SQL :
Hibernate:
values
nextval for amessage_sequence
2018-11-27 14:49:54.190 DEBUG 2791 --- [ restartedMain] org.hibernate.SQL :
Hibernate:
insert
into
messages
(body, message_code)
values
(?, ?)
2018-11-27 14:49:54.191 TRACE 2791 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [This is a test message]
2018-11-27 14:49:54.193 TRACE 2791 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [2922079]
2018-11-27 14:49:54.196 DEBUG 2791 --- [ restartedMain] org.hibernate.SQL :
Hibernate:
insert
into
message_recipient
(timestamp, message_id, message_to)
values
(?, ?, ?)
2018-11-27 14:49:54.196 TRACE 2791 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [TIMESTAMP] - [2018-11-27 14:49:54.141]
2018-11-27 14:49:54.196 TRACE 2791 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [null]
2018-11-27 14:49:54.196 TRACE 2791 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARCHAR] - [RecipientName]
2018-11-27 14:49:54.199 WARN 2791 --- [ restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: -407, SQLState: 23502
2018-11-27 14:49:54.199 ERROR 2791 --- [ restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper : DB2 SQL Error: SQLCODE=-407, SQLSTATE=23502, SQLERRMC=TBSPACEID=7, TABLEID=21, COLNO=1, DRIVER=4.19.26
Я исчерпал все возможности, которые я могу придумать, чтобы попытаться заставить это работать, включая @IdClass, но всегда нулевой.Из всего, что я могу найти в Интернете, это должно работать.Я нашел один или два похожих SO вопроса, но ни один из них не касался специфики составного ключа, где одно из составных полей - это родительский идентификатор.
Я думаю, что могу обойти это, сохранив Сообщение и Получателей вдва отдельных состояния (сохранение сообщения, получение идентификатора, а затем создание и сохранение получателей), но, насколько я знаю, это должно работать ...