@EmbeddedId

时间:2019-06-13 09:54:48

标签: java hibernate jpa orm nhibernate-mapping

如果我使用这段代码(图片中的案例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中一样。

enter image description here

如何在案例1中更新对象2以反映数据库ID?

更新

在下面的讨论之后-问题是,如果将实体上的@12081手动设置为某个值,Spring认为它不是新实体,而是尝试合并而不是保留该实体。

“变通办法”之一是在id@Version上设置@Entity字段,该字段将跟踪实体是否为新实体。

PostOneUni

1 个答案:

答案 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的地方,然后返回原始(相同)实例,并且将在该实例上正确设置标识符。