我有Entity
包含Embeddable
个对象的集合,如下所示:
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "as")
public class A {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ElementCollection
private Set<B> bs;
public B getB(String name) {
for(B b : bs)
if(b.getName().equals(name))
return b;
return null;
}
public void addB(B b) {
if(!bs.add(b))
throw new IllegalArgumentException("Duplicate ......");
}
....
}
@Embeddable
public class B {
@Column(nullable = false)
private String name;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false)
private Date creationTimestamp;
}
我正在使用Spring Data加载和保存我的实体,如下所示:
Optional<A> a = aRepository.findById(aId);
B b = a.getB(...);
if(b == null) {
b = new B(...);
a.addB(b);
}
aRepository.save(a);
上面的代码是使用@Transactional
注释的方法。
当方法返回时,我可以在数据库中看到3个重复的可嵌入对象,而不是一个。
有什么想法吗?
修改
经过长时间的调试,我可以确认Hibernate只为我添加的单个实例插入一行。但是,当我从我的REST控制器返回创建的对象时,在某些时候,Jackson对象映射器在将对象发送回客户端之前序列化我的对象,这里发生了剩下的两个INSERT ......我以前从未见过它。 ..任何帮助将不胜感激
更多信息:
当SessionRepository提交会话更改时,最后2个INSERT完成 - 我确切地说我使用了Spring Session。如果这可以帮助......
答案 0 :(得分:0)
问题发生在bs.add(b)
。 Set
添加一个对象将检查该对象是否存在于集合中。但在您的情况下,由于b
,对象creationTimestamp
将始终与现有对象不同。 creationTimestamp
与现有对象不同。因为你是新对象,所以时间将是当前的数据时间。因此bs.add(b)
始终为true
。
尝试删除creationTimestamp
并重新运行代码以验证此操作。
您需要覆盖B
的equals()和hashCode()