Spring JPA data is inserted with the child along with the parent, taking the identifier from the parent

I want to save the parent with the child in the MySQL database, just by calling save parent. There is a one-to-one mapping between parent and child objects. The parent id is automatically generated, and we should use it also as a child pk.

I am using Spring Data JPA 2.0 (JPA provider - Hibernate) and Spring MVC. When you try to insert an object, I get the following error.

The main reason

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 the schema of My DB:

 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 object:

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

Baby 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); 
+5
source share
2 answers

You must use a cascade in both of your objects. Try the following:

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

An 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 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 in accordance with JPA Docs :

Denotes a ManyToOne or OneToOne relationship attribute that maps the EmbeddedId primary key, the attribute within the EmbeddedId primary key, or the parent's simple primary key. The value element indicates the attribute within the composite key to which the relation attribute corresponds. If the primary key of the object is of the same Java type as the primary key of the object referenced by the relationship, the value attribute is not specified.

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

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

Source: https://habr.com/ru/post/1201085/


All Articles