【发布时间】:2019-10-01 16:51:25
【问题描述】:
我尝试使用 spring-data-jpa 和休眠来保存多对多关系。这两个类都有复合键。我正在使用列出两个类的连接类。我收到一个错误,暗示该对象已经存在。我不知道我在这里做错了什么。这是我的代码:
交易
@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
交易标签
@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]
...
...
编辑
有人建议我删除Transaction中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
【问题讨论】:
标签: hibernate spring-data-jpa composite-key