Hi,
as I promised, here is the code that works for me.
I used reflection, if this could be done by hibernate much easier, I would be glad to know it.
But be aware, that it is very error-prone and it was much harder to do, than I taught in the first place.
Especially it was quite hard to stop recursion and to avoid a stack-overflow.
Nevertheless it was a good training in reflection.
But as soon as I have some spare time, I will switch to a clone able hierarchy. Cause I don't fell very well with this solution.
Code:
private static boolean checkBasicTypes(final Object o) {
if (!(o instanceof Number) && !(o instanceof Boolean) && !(o instanceof Byte)
&& !(o instanceof Character) && !(o instanceof Void)) {
return false;
}
return true;
}
private static boolean checkPrimitives(final Field f) {
if (f.getType() != Long.TYPE && f.getType() != Boolean.TYPE && f.getType() != Short.TYPE
&& f.getType() != Integer.TYPE && f.getType() != Float.TYPE && f.getType() != Double.TYPE
&& f.getType() != Byte.TYPE && f.getType() != Character.TYPE && f.getType() != Void.TYPE) {
return false;
}
return true;
}
private static List<Field> getAllDeclaredFields(final Object o) {
final List<Field> fields = new ArrayList<Field>();
if (o != null && !(o instanceof Logger)) {
Class<?> clazz = o.getClass();
do {
try {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
// System.out.println(clazz.getName());
}
catch (final Exception e) {
e.printStackTrace();
}
}
while ((clazz = clazz.getSuperclass()) != null);
}
return fields;
}
public static void nullAllObjectIDs(final Object o) throws IllegalAccessException {
if (o != null) {
final List<Field> fields = getAllDeclaredFields(o);
for (final Field f : fields) {
f.setAccessible(true);
final Object fieldValue = f.get(o);
if (fieldValue instanceof Collection || fieldValue instanceof Map
|| (fieldValue != null && fieldValue.getClass().isArray())) {
if (fieldValue.getClass().isArray()) {
// System.out.println("Array " + o.getClass().getName()
// + " " + f.getName());
for (int i = 0, n = Array.getLength(fieldValue); i < n; i++) {
final Object data = Array.get(fieldValue, i);
if (!checkBasicTypes(data) && !(data instanceof String)) {
nullAllObjectIDs(data);
}
}
}
if (fieldValue instanceof List) {
// System.out.println("List " + o.getClass().getName() +
// " " + f.getName());
final List<?> list = (List<?>) fieldValue;
for (final Object l : list) {
nullAllObjectIDs(l);
}
}
if (fieldValue instanceof Map) {
// System.out.println("Map " + o.getClass().getName() +
// " " + f.getName());
final Map<?, ?> map = (Map<?, ?>) fieldValue;
if (!(map instanceof EnumMap)) {
for (final Object l : map.keySet()) {
if (!(l instanceof String) && !checkBasicTypes(l)) {
nullAllObjectIDs(l);
}
}
}
for (final Object l : map.values()) {
nullAllObjectIDs(l);
}
}
if (fieldValue instanceof Set) {
// System.out.println("Set " + o.getClass().getName() +
// " " + f.getName());
final Set<?> set = (Set<?>) fieldValue;
for (final Object l : set) {
nullAllObjectIDs(l);
}
}
}
else {
/* Avoid null setting of compound ID's */
if (!(o instanceof CountryModel)) {
final Annotation[] annotations = f.getAnnotations();
for (final Annotation a : annotations) {
if (a instanceof javax.persistence.Id) {
System.out.println("ID chnage: " + o.getClass().getName() + "\t"
+ f.getName());
f.set(o, null);
break;
}
}
}
/*
* Avoids inifitive loop, cause primitives have primitives
* as fields. Also Number, String and Enum aren't part of
* any direct relation. So stop unecassry rekursion.
*/
if (!checkPrimitives(f) && !checkBasicTypes(fieldValue)
&& !(fieldValue instanceof String) && !(fieldValue instanceof Class)
&& !(fieldValue instanceof Enum) && !(fieldValue instanceof StringBuffer)
&& !(fieldValue instanceof Collator) && !(fieldValue instanceof Method)
&& !(fieldValue instanceof Calendar)) {
try {
// System.out.println("None Basic Attribute " +
// o.getClass().getName() + "\t"
// + f.getName());
nullAllObjectIDs(fieldValue);
}
catch (final IllegalAccessException iae) {
iae.printStackTrace();
}
}
}
f.setAccessible(false);
}
}
}
Countrymodel has a compound key, which had be changed before.
Hope this will help someone out here. Even it is not recommend.
Greetings Michael