Save child objects automatically with JPA Hibernate

I have a one-to-many relationship between parent and child table. In the parent object I have

List<Child> setChilds(List<Child> childs) 

I also have a foreign key in the Child table. This foreign key is an identifier that refers to the parent row in the database. Therefore, in my database configuration, this foreign key cannot be NULL. Also, this foreign key is the primary key in the parent table.

So my question is how can I automatically save child objects by doing something like this:

 session.save(parent); 

I tried above, but I am getting a database error complaining that the foreign key field in the Child table cannot be NULL. Is there a way to tell JPA to automatically set this foreign key to a Child object so that it can automatically save child objects?

Thanks in advance.

+42
java database hibernate
Oct 13 2018-10-10
source share
6 answers

I tried above, but I am getting a database error complaining that the foreign key field in the Child table cannot be NULL. Is there a way to tell JPA to automatically set this foreign key to a Child object so that it can automatically save child objects?

Well, there are two things.

First, you need to cascade the save operation (but I understand that you are doing this or you will not get a violation of the FK constraint during inserts in the "child" table)

Secondly, you probably have a bi-directional connection, and I think that you are not setting the β€œboth sides of the link” correctly. You should do something like this:

 Parent parent = new Parent(); ... Child c1 = new Child(); ... c1.setParent(parent); List<Child> children = new ArrayList<Child>(); children.add(c1); parent.setChilds(children); session.save(parent); 

A common example is the use of link management methods:

 @Entity public class Parent { @Id private Long id; @OneToMany(mappedBy="parent") private List<Child> children = new ArrayList<Child>(); ... protected void setChildren(List<Child> children) { this.children = children; } public void addToChildren(Child child) { child.setParent(this); this.children.add(child); } } 

And the code will look like this:

 Parent parent = new Parent(); ... Child c1 = new Child(); ... parent.addToChild(c1); session.save(parent); 

References

+41
Oct. 14 '10 at 21:48
source share

I believe that you need to set the cascade parameter in your mapping through xml / annotation. Refer to the Hibernate link example here .

If you use annotation, you need to do something like this,

 @OneToMany(cascade = CascadeType.PERSIST) // Other options are CascadeType.ALL, CascadeType.UPDATE etc.. 
+12
Oct. 14 '10 at 4:21
source share

Here are ways to assign a parent to a child of a bidirectional relationship <

Suppose you have a one-to-many relationship, then for each parent object there is a set of child objects. In a bidirectional relationship, each child will have a reference to its parent.

 eg : Each Department will have list of Employees and each Employee is part of some department.This is called Bi directional relations. 

To achieve this, in one way, you must assign the parent to the child, keeping the parent

 Parent parent = new Parent(); ... Child c1 = new Child(); ... c1.setParent(parent); List<Child> children = new ArrayList<Child>(); children.add(c1); parent.setChilds(children); session.save(parent); 

Another way : you can use hibernate Intercepter, so you cannot write the code above for all models.

Hibernate interceptor provides apis to do your own work before doing any database operation. Like an onSave object, we can assign a parent object to child objects using reflection.

 public class CustomEntityInterceptor extends EmptyInterceptor { @Override public boolean onSave( final Object entity, final Serializable id, final Object[] state, final String[] propertyNames, final Type[] types) { if (types != null) { for (int i = 0; i < types.length; i++) { if (types[i].isCollectionType()) { String propertyName = propertyNames[i]; propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); try { Method method = entity.getClass().getMethod("get" + propertyName); List<Object> objectList = (List<Object>) method.invoke(entity); if (objectList != null) { for (Object object : objectList) { String entityName = entity.getClass().getSimpleName(); Method eachMethod = object.getClass().getMethod("set" + entityName, entity.getClass()); eachMethod.invoke(object, entity); } } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } } } } return true; } } 

And you can register Intercepter for configuration as

 new Configuration().setInterceptor( new CustomEntityInterceptor() ); 
+2
Sep 09 '16 at 9:13
source share

Use org.hibernate.annotations to execute Cascade , if hibernate and JPA , it somehow complains about saving child objects.

+1
Mar 03 '17 at 6:30
source share

in your setChilds, you can try to loop through the list and do something like

 child.parent = this; 

You must also set the parent cascade to the appropriate values.

0
Oct 13 '10 at 19:10
source share

The following program describes how the bidirectional ratio works in sleep mode. When a parent saves his list of child objects, it will be automatically saved.

  @Entity @Table(name="clients") public class Clients implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @OneToMany(mappedBy="clients", cascade=CascadeType.ALL) List<SmsNumbers> smsNumbers; on the parent side and put the following annotation on the child side @Entity @Table(name="smsnumbers") public class SmsNumbers implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) int id; String number; String status; Date reg_date; @ManyToOne @JoinColumn(name = "client_id") private Clients clients; and getter setter. public static void main(String arr[]) { Session session = HibernateUtil.openSession(); //getting transaction object from session object session.beginTransaction(); Clients cl=new Clients("Murali", "1010101010"); SmsNumbers sms1=new SmsNumbers("99999", "Active", cl); SmsNumbers sms2=new SmsNumbers("88888", "InActive", cl); SmsNumbers sms3=new SmsNumbers("77777", "Active", cl); List<SmsNumbers> lstSmsNumbers=new ArrayList<SmsNumbers>(); lstSmsNumbers.add(sms1); lstSmsNumbers.add(sms2); lstSmsNumbers.add(sms3); cl.setSmsNumbers(lstSmsNumbers); session.saveOrUpdate(cl); session.getTransaction().commit(); session.close(); 
0
Aug 08 '17 at 16:16
source share



All Articles