java Spring Data JPA 通过从父级获取 id 与子级和父级实体一起插入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25490774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:06:39  来源:igfitidea点击:

Spring Data JPA insert with child along with parent entity by taking id from parent

javahibernatespring-data-jpaparent-childjpa-2.0

提问by Mangesh Pathak

I want to save Parent entity along with child entity into MySQL database by just calling save on parent. There is one to one mapping between Parent and Child entities. Parent ID is auto generated and we need to use same in the child as child's pk also.

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

I am using Spring Data JPA 2.0 (the JPA provider is Hibernate) and Spring MVC framework. When are tried to insert entity I am getting following error.

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

root cause

根本原因

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)

Here is My DB Schema:

这是我的数据库架构:

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;

Here is my Java Entity Parent Entity:

这是我的 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
}

Child Enity:

子实体:

@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
}

Here is my Main method

这是我的主要方法

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);

回答by Viacheslav Shalamov

You should use cascade in both your objects. Try this:

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

@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;
    //...
}

回答by Chaitanya

The exception

例外

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

says that the parentproperty in your Childobject is null.

parent你的Child对象中的属性是null.



So to fix this you need to add this line of code:

因此,要解决此问题,您需要添加以下代码行:

child.setParent(parent);

Also as per the JPA Docs:

同样根据JPA 文档

Designates a ManyToOne or OneToOne relationship attribute that provides the mapping for an EmbeddedId primary key, an attribute within an EmbeddedId primary key, or a simple primary key of the parent entity. The value element specifies the attribute within a composite key to which the relationship attribute corresponds.If the entity's primary key is of the same Java type as the primary key of the entity referenced by the relationship, the value attribute is not specified.

指定 ManyToOne 或 OneToOne 关系属性,该属性提供 EmbeddedId 主键、EmbeddedId 主键内的属性或父实体的简单主键的映射。value 元素指定关系属性对应的组合键中的属性。如果实体的主键与关系引用的实体的主键的 Java 类型相同,则不指定 value 属性。

your parentfield in Childclass should be declared without the valueattribute for @MapsId:

parentChild类中的字段应该在没有value属性的情况下声明@MapsId

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