Hi all.
I was under quite a lot of pressure a few weeks ago to deliver a tech demo of a project I was working on; I'm using the JPA for Database comms and I needed to find a VERY quick way to do some basic Insert - Update - Delete operations on the Database. So I came up with the the following example method using Reflection to insert records into the Database. I KNOW its NOT good practise since Reflection is comparatively slow - and I since HAVE changed my project to use Standard JPA Entity Access methods.
My question is this:
I thought it would be really cool if I could write a Generic class that can Communicate with ANY of my Entity Objects without having to know the particulars of the methods and datatypes of the fields inside the Entity. So firstly - is it possible to convert the code below to act in a similar way using Generics? And secondly - would anybody advise against it? And thirdly - If it is possible - could anybody please point me in the right direction on how exactly to go about doing it?
Oh - and I'm NOT an expert on Generics AT ALL - but I would like to attempt to implement a Generic method as described above...
And please - I know my code isn't perfect - this was written in an intense hurry... So please bear with any inadequacies...
The Reflection code:
/**
* Temporary helper class - find a better way to do this in the future.
* This is a reflective method which will persist data from a hashmap
* to an Entity Class and commit the changes to the underlying Database.
* The String keys in the HashMap MUST map to the Methods
* in the persistence Entity, and the values will be persisted by the Entity method
* identified by the HashMap key.
* <BR>
* @param table The name of the Database Entity Class to persist to.
* @param map The HashMap containing the Method keys and their corresponding values
* @return Object - The Persistence Entity Object if persistence succeeded, Null if not. If Null is returned,
* check the Log for further details.
*/
public Object persist(String table, java.util.HashMap<String, Object> map) {
Object instance = null;
Object value = null;
Object ret = null;
javax.persistence.EntityManager OrderManagementPersistenceUnitEntityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("OrderManagementPersistenceUnit").createEntityManager();
//Attempt to commit the new record:
javax.persistence.EntityTransaction tx = OrderManagementPersistenceUnitEntityManager.getTransaction();
tx.begin();
try {
//Get Entity Class & instance
Class c = Class.forName(table);
instance = c.getConstructor((Class[]) null).newInstance((Object[])null);
//Get Methods in Entity Class
java.lang.reflect.Method[] m = c.getDeclaredMethods();
//Loop over methods and find the methods that match the HashMap Key
for(int x = 0; x < m.length; x++) {
if(map.containsKey(m[x].getName())) {
System.out.println("Method operation: " + m[x].getName());
//Set value variable to the value identified by the HashMap Key
value = map.get(m[x].getName());
Class[] paramTypes = m[x].getParameterTypes();
if((paramTypes != null) && (paramTypes.length > 0)) {
System.out.println(c.getName() + ": Calling method code -> " + m[x].getName() + "(new " + paramTypes[0].getName() + "(\"" + value.toString() + "\"));");
if(!paramTypes[0].isPrimitive()) {
//Need to use Class.cast for non-primitive data-types
//Invoke method in Entity Object.
m[x].invoke(instance,paramTypes[0].cast(value));
} else {
//Invoke method in Entity Object.
m[x].invoke(instance,value);
}
} else {
//Invoke method in Entity Object.
m[x].invoke(instance,value);
}
if((paramTypes != null) && (paramTypes.length > 0)) {
System.out.println(c.getName() + ": Called -> " + m[x].getName() + "(new " + paramTypes[0].getName() + "(\"" + value.toString() + "\")); -> SUCCESS!");
}
}
}
//Commit Entity Object changes...
OrderManagementPersistenceUnitEntityManager.merge(instance);
OrderManagementPersistenceUnitEntityManager.flush(); //Only called due to some UI problems -> it works now.
tx.commit();
ret = instance;
//Rollback and log failed transactions.
} catch (SecurityException ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} catch (IllegalAccessException ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} catch (IllegalArgumentException ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} catch (InvocationTargetException ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} catch (ClassNotFoundException ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} catch(Exception ex) {
Logger.getLogger(persistToDatabase.class.getName()).log(Level.SEVERE, null, ex);
ret = null;
tx.rollback();
} finally {
OrderManagementPersistenceUnitEntityManager.close();
return ret;
}
}
Any help would be greatly appreciated...