java - Spring JPA @ManyToOne 保存因重复 key 而失败

标签 java spring hibernate spring-data-jpa

我有以下实体:

@Entity
@Data
@Table(name = "Parents")
public class Parent {
    @Id
    @GeneratedValue
    Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "child")
    private Child child;
}

还有

@Entity
@Data
@Table(name = "Childs")
public class Child {
    @Id
    String number;
}

对于这两个实体,我都有一个标准的 CrudRepository。在应用程序启动时,我尝试使用以下代码填充数据库:

@Component
public class TestFiller implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    ParentRepository parentRepository;

    @Autowired
    ChildRepository childRepository;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        for (int i = 0; i < 100; i++) {
            Parent parent = new Parent();

            String childId = "CHILD" + Math.round(Math.random() * 10);
            Optional<Child> childOpt = childRepository.findById(childId);
            if (childOpt.isPresent()) {
                parent.setChild(childOpt.get());
            } else {
                Child child = new Child();
                child.setNumber(childId);
                parent.setChild(child);
            }

            parentRepository.save(parent);
        }
    }
}

这是子存储库:

@Repository
public interface ChildRepository extends JpaRepository<Child, String> {
}

但是由于某些莫名其妙的原因,当数据库中已经存在子项时,此操作会失败:

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "childs_pkey"
  Detail: Key (number)=(CHILD6) already exists.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:645) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:495) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:441) ~[postgresql-9.4-1206-jdbc42.jar:9.4]

看起来 findById 方法返回的实体几乎不受管理。为什么 Hibernate/JPA 试图保留现有实体?

编辑:根据请求我添加了 ChildRepository

最佳答案

好的,回答我自己的问题:

它是由 ParentChild 属性上的 CascadeType @ManyToOne(cascade = CascadeType.ALL) 引起的。删除它即可解决问题。

显然,JPA 也将 PERSIST 操作级联到 Child,即使它可以很容易地知道 Child 已经是托管和持久实体。

关于java - Spring JPA @ManyToOne 保存因重复 key 而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49978469/

相关文章:

spring - 如何检查服务是否实现了grails中的接口(interface)

java - 在对象的同一个表中显示 OneToMany 列表的大小?

java - Spring hibernate : Illegal attempt to associate a collection with two open sessions

java - 同步块(synchronized block)/方法可以被中断吗?

java - 使用模式和匹配器搜索特殊字符(示例 : $)

java - 访问静态类字段的更好方法

java - android:gravity 在 API 18+ 上失败

java - Spring 。 AutoWired 对象 NullPointerException

java - Spring Integration 的并发问题 - "Cannot publish to a deleted Destination"

Spring Boot 2.0.0 迁移 - JPA 存储库保存问题