使用Spring Data JPA插入而不是更新

时间:2016-03-12 23:31:41

标签: java spring hibernate jpa spring-data-jpa

我有一个简单的模型。实体A与实体B具有一对多关系。它们使用关联表链接。我的用例是在简单的Web应用程序中获取/插入/更新实体:

  1. 将实体A提取为JSON。
  2. 将实体A(甚至不变)保存。
  3. 约束违规:hibernate尝试将现有行插入关联表。
  4. 为什么会这样? Hibernate拥有确定是否应该对父项及其子项进行合并或持久化所需的一切。为什么它不检查孩子是否已经与父母联系?

    Parent.java:

    package com.example;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Version;
    
    import lombok.EqualsAndHashCode;
    
    @Entity
    @EqualsAndHashCode(exclude = { "id" })
    public class Parent {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
        private Set<Child> children = new HashSet<>();
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Set<Child> getChildren() {
            return children;
        }
    
        public void setChildren(Set<Child> children) {
            this.children = children;
        }
    
    }
    

    Child.java

    package com.example;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Version;
    
    import lombok.EqualsAndHashCode;
    
    @Entity
    @EqualsAndHashCode(exclude = { "id" })
    public class Child {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private Long value;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Long getValue() {
            return value;
        }
    
        public void setValue(Long value) {
            this.value = value;
        }
    
    }
    

    ParentService.java:

    package com.example;
    
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import javax.persistence.EntityManager;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
        @Service
        public class ParentService {
    
            @Autowired
            private ParentRepository parentRepository;
    
            @Transactional
            public Parent save(Parent parent) {
                return parentRepository.save(parent);
            }
    
        }
    

    ParentRepository.java:

    package com.example;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ParentRepository extends JpaRepository<Parent, Long>{
    
    }
    

    当我添加@Version属性然后一切正常时,有趣的是,但我找不到解释原因。另一个解决方案是通过id获取oldParent,只是为了获取 - 然后它也可以工作,即使没有@Version,但是当我将获得oldParent子节点并使用size()再次初始化它时,不希望的插入即将到来。为什么这些东西都有效?它与Hibernate或Spring Data JPA存储库有关吗?

1 个答案:

答案 0 :(得分:-1)

您写道:'他们使用关联表链接'

你真的很舒服吗?

ManyToOne的默认映射是许多方面的附加外键。在您的情况下,表子项应该有一个额外的字段'parent_id',并且没有其他关联表。 每个孩子都可以与父母一方完全联系。

也许您可以发布'hibernate尝试将现有行插入关联表'的异常?