如果我使用这段代码(图片中的案例1):
@Data
@Entity
public class PostOneUni {
@EmbeddedId //if @Id, class CompositeId must be annotated @Embeddable?
private CompositeId id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumns({
@JoinColumn(name = "id1"),
@JoinColumn(name = "id2")
})
private Set<PostCommentUniMany> comments = new HashSet<>();
...
}
,并且在执行此对象的创建并添加子注释时,将所有内容保存到数据库时都按预期进行(子PostCommentUniMany
上的ID已按预期添加),但是更改不会传播到Java代码(对象{{1 }}图片中的@12081
字段应更新为id
,而不是2
)。
在其他情况下(案例2),我使用以下代码:
null
,从图片中可以看到,字段也保留在DB中,并且在保存后更新了用于将状态保存到DB的对象(对象@Data
@Entity
public class PostOneUni {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private Set<PostCommentUniMany> comments = new HashSet<>();
...
}
已更新为反映@12052
字段为id
-与DB中一样。
如何在案例1中更新对象2
以反映数据库ID?
更新
在下面的讨论之后-问题是,如果将实体上的@12081
手动设置为某个值,Spring认为它不是新实体,而是尝试合并而不是保留该实体。
“变通办法”之一是在id
类@Version
上设置@Entity
字段,该字段将跟踪实体是否为新实体。
PostOneUni
答案 0 :(得分:1)
问题在于,因为您已手动设置了ID字段,所以Spring Data会调用合并操作,而不是持久化:
请参见org.springframework.data.jpa.repository.support.SimpleJpaRepository
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) //checks if ID null {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
JPA规范指出,当
3.2.7.1合并独立的实体状态
•如果X是新的实体实例,则新的管理实体实例X'为 创建并将X的状态复制到新的受管实体 实例X'。
如果要这样做,请在测试代码中
post = oneToManyService.addNewPost(post);
在返回的实例上正确设置了标识符,就像从数据库中重新加载时一样。但是,原始实例(处于“新”状态)保持不变,即未设置ID。
在调用persist而不是merge的地方,然后返回原始(相同)实例,并且将在该实例上正确设置标识符。