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

17,429

Solution 1

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

Solution 2

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 parent property in your Child object is null.


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

child.setParent(parent);

Also as per the JPA Docs:

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.

your parent field in Child class should be declared without the value attribute for @MapsId :

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="cid")
@MapsId
private Parent parent;
Share:
17,429
Mangesh Pathak
Author by

Mangesh Pathak

Updated on June 16, 2022

Comments

  • Mangesh Pathak
    Mangesh Pathak over 1 year

    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.

    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.

    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:

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