I have a one-to-many relation between Parent and Child table. In the parent object I have a
List setChildren(List childs)
I believe you need to set the cascade option in your mapping via xml/annotation. Refer to Hibernate reference example here.
In case you are using annotation, you need to do something like this,
@OneToMany(cascade = CascadeType.PERSIST) // Other options are CascadeType.ALL, CascadeType.UPDATE etc..
in your setChilds, you might want to try looping thru the list and doing something like
child.parent = this;
you also should set up the cascade on the parent to the appropriate values.
Here are the ways to assign parent object in child object of Bi-directional relations ?
Suppose you have a relation say One-To-Many,then for each parent object,a set of child object exists. In bi-directional relations,each child object will have 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, one way is to assign parent in child object while persisting parent object
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);
Other way is, you can do using hibernate Intercepter,this way helps you not to write above code for all models.
Hibernate interceptor provide apis to do your own work before perform any DB operation.Likewise onSave of object, we can assign parent object in 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 to configuration as
new Configuration().setInterceptor( new CustomEntityInterceptor() );
In short set cascade type to all , will do a job; For an example in your model. Add Code like this . @OneToMany(mappedBy = "receipt", cascade=CascadeType.ALL) private List saleSet;
Following program describe how bidirectional relation work in hibernate.
When parent will save its list of child object will be auto save.
On Parent side:
@Entity
@Table(name="clients")
public class Clients implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@OneToMany(mappedBy="clients", cascade=CascadeType.ALL)
List<SmsNumbers> smsNumbers;
}
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.
}
Main class:
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();
}
Use org.hibernate.annotations
for doing Cascade
, if the hibernate
and JPA
are used together , its somehow complaining on saving the child objects.