【问题标题】:Spring Data JPA insert with child along with parent entity by taking id from parent通过从父实体获取 id,Spring Data JPA 将子实体与父实体一起插入
【发布时间】:2023-03-19 12:10:01
【问题描述】:

我想通过调用父实体的保存将父实体和子实体一起保存到 MySQL 数据库中。父实体和子实体之间存在一对一的映射。父母 ID 是自动生成的,我们也需要在孩子中使用与孩子的 pk 相同的 ID。

我正在使用 Spring Data JPA 2.0(JPA 提供者是 Hibernate)和 Spring MVC 框架。 尝试插入实体时出现以下错误。

根本原因

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.serro.cbmapi.model.Child.parent; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.serro.cbmapi.model.Child.parent org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:207)

这是我的数据库架构:

Parent Table:
   CREATE TABLE `parent` (
   `pid` int(11) NOT NULL AUTO_INCREMENT,
   `parent_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
    PRIMARY KEY (`pid`)    ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Child Table:
    CREATE TABLE `child` (
    `cid` int(11) NOT NULL,
    `child_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
    PRIMARY KEY (`cid`),
    CONSTRAINT `child_f1` FOREIGN KEY (`cid`) REFERENCES `parent` (`pid`)

    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

这是我的 Java 实体 父实体:

@Entity(name="parent")
@NamedQuery(name="Parent.findAll", query="SELECT p FROM parent p")
public class Parent implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private int pid;

    @Column(name="parent_name")
    private String parentName;

    //bi-directional one-to-one association to Child
    @OneToOne(mappedBy="parent",cascade=CascadeType.ALL)
    private Child child;

    //getter, setters
}

子实体:

@Entity(name="child")
@NamedQuery(name="Child.findAll", query="SELECT c FROM child c")
public class Child implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private int cid;

    @Column(name="child_name")
    private String childName;

    //bi-directional one-to-one association to Parent
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="cid")
    @MapsId("cid")
    private Parent parent;

    //getter, setters
}

这是我的主要方法

AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
ParentRepository parentResp = context.getBean(ParentRepository.class);  
Parent parent = new Parent();
parent.setParentName("Parent1");
Child child = new Child();
child.setChildName("Child1");
parent.setChild(child);
parentResp.save(parent);

【问题讨论】:

    标签: java hibernate spring-data-jpa parent-child jpa-2.0


    【解决方案1】:

    异常

    not-null property references a null or transient value: com.serro.cbmapi.model.Child.parent; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.serro.cbmapi.model.Child.parent
    

    表示Child 对象中的parent 属性是null


    所以要解决这个问题,你需要添加这行代码:

    child.setParent(parent);
    

    同样根据JPA Docs:

    指定 ManyToOne 或 OneToOne 关系属性 提供 EmbeddedId 主键、属性的映射 在 EmbeddedId 主键或 母实体。 value 元素指定了一个内的属性 关系属性对应的复合键。 如果 实体的主键与主键的 Java 类型相同 关系引用的实体的值属性是 未指定。

    Child 类中的parent 字段应声明为不带@MapsIdvalue 属性:

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="cid")
    @MapsId
    private Parent parent;
    

    【讨论】:

      【解决方案2】:

      您应该在两个对象中都使用级联。试试这个:

      @Entity(name="parent")
      public class Parent implements Serializable {
          //...
          @OneToOne(mappedBy="parent",cascade=CascadeType.ALL)
          private Child child;
          //...
      }
      
      @Entity(name="child")
      public class Child implements Serializable {
          //...
          @OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
          @JoinColumn(name="cid", referencedColumnName = "id")
          private Parent parent;
          //...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-03
        • 2012-11-10
        • 1970-01-01
        • 2020-05-16
        • 1970-01-01
        • 2017-09-27
        • 2022-11-29
        相关资源
        最近更新 更多