У меня есть отношение многие ко многим, которое я пытаюсь сохранить, используя spring-data-jpa и hibernate.Оба класса имеют составные ключи.Я использую класс соединения с обоими классами в списке.Я получаю ошибку, которая подразумевает, что объект уже существует.Я не знаю, что я делаю здесь не так.Вот мой код:
Транзакция
@Entity
@Table(name = "transaction")
@IdClass(Transaction.TransactionPK.class)
public class Transaction {
@Id
private Long userId;
@Id
@GeneratedValue(generator = "transaction_generator")
@SequenceGenerator(
name = "transaction_generator",
sequenceName = "transaction_sequence",
initialValue = 1000,
allocationSize = 1
)
private Long transactionId;
@OneToMany(mappedBy = "transaction",
cascade = {CascadeType.PERSIST, CascadeType.MERGE}
)
private Set<TransactionTag> tags = new HashSet<>();
public void addTag(Tag tag) {
TransactionTag postTag = new TransactionTag(this, tag);
tags.add(postTag);
tag.getTransactions().add(postTag);
}
//getters and setters
static class TransactionPK implements Serializable {
private Long transactionId;
private Long userId;
public TransactionPK(Long userId, Long transactionId) {
this.userId = userId;
this.transactionId = transactionId;
}
public TransactionPK() {}
//equals, hashcode and getters and setters
Метка
@Entity
@Table(name = "tag", uniqueConstraints={
@UniqueConstraint(columnNames = {"userId", "tagName"})
})
@IdClass(Tag.TagPK.class)
public class Tag {
@Id
private Long userId;
@Id
@GeneratedValue(generator = "tag_generator")
@SequenceGenerator(
name = "tag_generator",
sequenceName = "tag_sequence",
initialValue = 1000,
allocationSize = 1
)
private Long tagId;
@NotNull
@Column(nullable = false)
private String tagName;
@OneToMany(
mappedBy = "tag",
cascade = {CascadeType.PERSIST, CascadeType.MERGE}
)
private Set<TransactionTag> transactions;
//getters and setters
static class TagPK implements Serializable {
private Long userId;
private Long tagId;
public TagPK(Long userId, Long tagId) {
this.userId = userId;
this.tagId = tagId;
}
//equals, hashcode and getters and setters
TransactionTag
@Entity
public class TransactionTag implements Serializable {
@EmbeddedId
private TransactionTagId id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="user_id", insertable = false, updatable = false),
@JoinColumn(name="transaction_id", insertable = false, updatable = false)
})
private Transaction transaction;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="user_Id", insertable = false, updatable = false),
@JoinColumn(name="tag_Id", insertable = false, updatable = false)
})
private Tag tag;
private TransactionTag() {}
public TransactionTag(Transaction transaction, Tag tag) {
this.transaction = transaction;
this.tag = tag;
this.id = new TransactionTagId(transaction.getTransactionId(),tag.getTagId());
}
//equals, hashcode and getters and setters
@Embeddable
static class TransactionTagId implements Serializable {
@Column(name = "transaction_id")
private Long transactionId;
@Column(name = "tag_id")
private Long tagId;
private TransactionTagId() {}
public TransactionTagId(
Long transactionId,
Long tagId) {
this.transactionId = transactionId;
this.tagId = tagId;
}
//equals, hashcode and getters and setters
Сервисный код
public Transaction save(Long userId, TransactionDto transactionDto) {
Transaction transaction = new Transaction();
if(transactionDto.getTags()!=null && transactionDto.getTags().size()>0) {
for(Long tagId:transactionDto.getTags()) {
Tag tag = tagService.findByUserIdAndTagId(userId, tagId);
transaction.addTag(tag);
}
}
return transactionRepo.saveAndFlush(transaction);
Я получаю следующую ошибку:
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.checking.register.model.TransactionTag#com.checking.register.model.TransactionTag$TransactionTagId@7a9]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:123) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1460) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1440) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
...
...
Редактировать
Было предложено удалить одну из строк в методе addTag()
в транзакции.Если я удаляю третью строку, я получаю:
Hibernate: insert into transaction_tag (tag_id, transaction_id) values (?, ?)
2019-05-15 11:19:45.128 WARN 29144 --- [nio-5000-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2019-05-15 11:19:45.134 ERROR 29144 --- [nio-5000-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "user_id" violates not-null constraint
Detail: Failing row contains (null, null, 1000, null, null, null, null).
Если я удаляю вторую строку, я получаю:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.checking.register.model.TransactionTag.transaction -> com.checking.register.model.Transaction