Bulk operations with Hibernate, will always leads to performence issues Because the operations are performed over the Object graph. If the objects are involved in too many associations, then some times the operation will not successed at all. Lets take the problem with Hibernate Delete operation over a data object with lot of associations. Full length object graph is loaded in to the memory before it deletes this object. But for deleting, we don’t need to load them, which is not hibernate behaviour.

As a hack to over come this loading object graph into the memory before deleting, we can construct the delete queries over the child collections. but we have to start firing this deleting query over the last rechable collection and this should be repeated over each and every associated child in a recursive way. If we know all the associations, then we can write the delete queries by our own and done with our task. but tomorrow, if somebody changed the mappings of your entity, then your method failed to delete.

We can do this in more generic way, by getting all the meta data information about the given Entity from the Hibernate class called AbstractEntityPersistar. An instance of this class is created for each entity that your are persisting with Hibernate. you can get this object of your entity from the session factory in the following way.

Map allClassMeta = sessionFactory.getAllClassMetadata();
AbstractEntityPersister persister = allClassMeta.get(“com.base.YourEntityObjectName”);

Once you have the persistor object with you, you can get all the meta information about the entity from the persistor object. For example

String[] properties = persister.getPropertyNames();
CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles();
for (int i = 0; i < properties.length; i++) {
if (persister.getPropertyTypes()[i] instanceof CollectionType ) {
if(cascadeStyles[i].doCascade(CascadingAction.DELETE)) { //handling collection columns with cascade delete enabled
reachableCollectionMap.put(role, colPersister);
}else{
/*
* for this collection cascade delete is disabled.
* we just have to set its FK value to null
*/
nullableCollectionMap.put(role, colPersister);
}

Here we are pushing all the reachable collections in to a hashmap. Depending on the entity mapping options for cascade attribute, we have to fire delete query on some collections and update query on some collections to set the refereces to null. ( we have to consider the value of inverse attribute also)

Before firing deleting query over the reachable collection, we have to delete the associations of each of the entity in the reachable collection also. so recursivly, we have to repeat this process for all the entities of the reachable collection, untill we did not find an associated collection and then start firing delete queries from there. like

private void runDeleteQuery(DeleteEntityWrapper deleteEntityWrapper) {

if (deleteEntityWrapper.hasChildEntities()) {
for (DeleteEntityWrapper childWrapper : deleteEntityWrapper
.getChildEntities()) {
if(deleteEntityWrapper.parent==null || !childWrapper.getTableName().equals(deleteEntityWrapper.parent.getTableName()))
runDeleteQuery(childWrapper);
}
}
}

Importent thing to note while making a recrusive call is, We must have to stop the recursive call for self associations. Otherwise, this will become infinte ..!!