spring-boot - SpringBoot CascadeType ALL 与 MERGE 和分离实体

标签 spring-boot jpa

我有以下实体:

@Entity
@Getter @Setter @NoArgsConstructor @RequiredArgsConstructor
public class Link extends Auditable {

    @Id
    @GeneratedValue
    private Long id;

    @NonNull
    private String title;


    @NonNull
    private String url;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "link")
    private List<Comment> comments = new ArrayList<>();

    @Transient
    @Setter(AccessLevel.NONE)
    private String userAlias ;

    public String getUserAlias() {

        if(user == null)
            return "";

        return user.getAlias();


    }

    @ManyToOne
    private User user;

    public Long getUser() {
        if(user == null)
            return -1L;

        return user.getId();
    }

    public void addComment(Comment c) {
        comments.add(c);
        c.setLink(this);

    }




}

@Entity
@Getter @Setter @NoArgsConstructor @RequiredArgsConstructor
public class Comment extends Auditable{

    @Id
    @GeneratedValue
    private Long id;

    @NonNull
    private String comment;

    @ManyToOne(fetch = FetchType.LAZY)
    private Link link;

    public Long getLink() {
        return link.getId();
    }


}

如果我创建评论和链接,请将链接与评论相关联,然后保存即可。

例如:

Link link = new Link("Getting started", "url");
Comment c = new Comment("Hello!");
link.addComment(c);
linkRepository.save(link);

但是,如果我先保存评论:

Link link = new Link("Getting started", "url");
Comment c = new Comment("Hello!");
commentRepository.save(c);
link.addComment(c);
linkRepository.save(link);

我明白

Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on uk.me.dariosdesk.dariodemo.domain.Comment.link references an unknown entity: uk.me.dariosdesk.dariodemo.domain.Link
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:97) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1815) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1759) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1646) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:287) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:903) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:934) ~[hibernate-core-5.4.0.Final.jar:5.4.0.Final]

将级联类型从 ALL 更改为 MERGE 似乎可以解决问题并接受这两种实现。 (即:添加预先存在的评论或创建两者,然后通过链接保存)

1)这是为什么? 2) 使用 MERGE 而不是 ALL 时有什么需要注意的吗?

最佳答案

存储库保存方法检查实体是否存在。对于新实体,调用持久化,对于持久化实体,调用合并。

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

在第二个用例中,链接是新实体,因此调用 persist() 。使用 CascadeType.ALL persist() 级联到 Comment 实体。注释已经持久化,需要合并,persist() 失败。

如果使用 CascadeType.MERGE persist() 不会级联到 Comment。它不会失败。

关于spring-boot - SpringBoot CascadeType ALL 与 MERGE 和分离实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55210341/

相关文章:

java - MySQL-Server/Apache Tomcat 和使用 Hibernate/JPA 的 Tapestry 项目的组合使用什么配置?

spring - 如何在Spring(Spring Boot)中将外部配置资源包含到类路径中?

java - 在进入页面时创建了许多 session ,而不是一个。为什么?

Spring Security自定义表单登录不适用于自定义loginProcessingUrl,返回404

java - 找到多于一行具有给定标识符的行

hibernate - HHH000122 : IllegalArgumentException in class: ConsumerAgentAccount, 属性的getter方法:id

java - 实体组

java - apache qpid 与 spring boot 的集成

java - 如何为 spring-boot 和 hibernate 配置 liquibase-maven-plugin

hibernate - JPA - @OneToMany 更新