Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
*
* FRAMEWORK Lixbox
* ==================
*
* This file is part of lixbox-orm.
*
* lixbox-supervision is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lixbox-supervision is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lixbox-orm. If not, see
*
* @AUTHOR Lixbox-team
*
******************************************************************************/
package fr.lixbox.orm.hibernate.util;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.proxy.HibernateProxy;
import fr.lixbox.orm.entity.model.Dao;
/**
* Cette classe assure le détachement des entités. Il traite les problèmes de LazyLoading.
*
* @author ludovic.terral
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class HibernateDetachUtil implements Serializable
{
// ----------- Attributs -----------
private static final Log log = LogFactory.getLog(HibernateDetachUtil.class);
private static final long serialVersionUID = 201710031501L;
private static final int depthAllowed = 20;
private static final boolean throwExceptionOnDepthLimit = true;
private static final boolean dumpStackOnThresholdLimit = true;
private static final long millisThresholdLimit = 5000;
private static final int sizeThresholdLimit = 10000;
private static final HashCodeGenerator hashCodeGenerator = new SystemHashCodeGenerator();
public enum SerializationType
{
SERIALIZATION, JAXB
}
static interface HashCodeGenerator
{
Integer getHashCode(Object value);
}
static class SystemHashCodeGenerator implements HashCodeGenerator
{
@Override
public Integer getHashCode(Object value)
{
return System.identityHashCode(value);
}
}
// ----------- Methodes -----------
public static void nullOutUninitializedFields(Object value, SerializationType serializationType) throws IllegalAccessException, ClassNotFoundException, InstantiationException, InvocationTargetException, IntrospectionException
{
long start = System.currentTimeMillis();
Map checkedObjectMap = new HashMap<>();
Map> checkedObjectCollisionMap = new HashMap<>();
nullOutUninitializedFields(value, checkedObjectMap, checkedObjectCollisionMap, 0, serializationType);
long duration = System.currentTimeMillis() - start;
if (dumpStackOnThresholdLimit)
{
int numObjectsProcessed = checkedObjectMap.size();
if (duration > millisThresholdLimit || numObjectsProcessed > sizeThresholdLimit)
{
String rootObjectString = (value != null) ? value.getClass().toString() : "null";
log.warn(
"Detached [" + numObjectsProcessed + "] objects in [" + duration
+ "]ms from root object [" + rootObjectString + "]",
new Throwable("HIBERNATE DETACH UTILITY STACK TRACE"));
}
}
else
{
// 10s is really long, log SOMETHING
if (duration > 10000L && log.isDebugEnabled())
{
log.debug("Detached [" + checkedObjectMap.size() + "] objects in [" + duration
+ "]ms");
}
}
// help the garbage collector be clearing these before we leave
checkedObjectMap.clear();
checkedObjectCollisionMap.clear();
}
/**
* @param value
* the object needing to be detached/scrubbed.
* @param checkedObjectMap
* This maps identityHashCodes to Objects we've already detached.
* In that way we can quickly determine if we've already done the
* work for the incoming value and avoid taversing it again. This
* works well almost all of the time, but it is possible that two
* different objects can have the same identity hash (conflicts
* are always possible with a hash). In that case we utilize the
* checkedObjectCollisionMap (see below).
* @param checkedObjectCollisionMap
* checkedObjectMap maps the identityhash to the *first* object
* with that hash. In most cases there will only be mapping for
* one hash, but it is possible to encounter the same hash for
* multiple objects, especially on 32bit or IBM JVMs. It is
* important to know if an object has already been detached
* because if it is somehow self-referencing, we have to stop the
* recursion. This map holds the 2nd..Nth mapping for a single
* hash and is used to ensure we never try to detach an object
* already processed.
* @param depth
* used to stop infinite recursion, defaults to a depth we don't
* expectto see, but it is configurable.
* @param serializationType
* @throws InvocationTargetException
* @throws InstantiationException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws IntrospectionException
* @throws Exception
* if a problem occurs
* @throws IllegalStateException
* if the recursion depth limit is reached
*/
private static void nullOutUninitializedFields(Object value,
Map checkedObjectMap,
Map> checkedObjectCollisionMap, int depth,
SerializationType serializationType) throws IllegalAccessException, ClassNotFoundException, InstantiationException, InvocationTargetException, IntrospectionException
{
if (depth > depthAllowed)
{
String warningMessage = "Recursed too deep [" + depth + " > " + depthAllowed
+ "], will not attempt to detach object of type ["
+ ((value != null) ? value.getClass().getName() : "N/A")
+ "]. This may cause serialization errors later. ";
log.warn(warningMessage);
if (throwExceptionOnDepthLimit)
{
throw new IllegalStateException(warningMessage);
}
return;
}
if (null == value)
{
return;
}
Integer valueIdentity = hashCodeGenerator.getHashCode(value);
Object checkedObject = checkedObjectMap.get(valueIdentity);
if (null == checkedObject)
{
checkedObjectMap.put(valueIdentity, value);
}
else if (value == checkedObject)
{
return;
}
else
{
boolean alreadyDetached = false;
List