I am working with some code where the user sends in an object which can have upwards of 100 values to it. (Let's use a car for example).
updateDatabasePrep(carObject);
The car object COULD have things like name, milage, vin, color, etc... but say I only set the color and then pass the object.
In my method:
public void updateDatabasePrep(Car carObject){
NewObject myObject = newObject(); //Initialized, but empty
String x1 = carObject.getMilage();
String x2 = carObject.getColor();
String x3 = carObject.getName();
//These will hold null values no problem
//Once the rest of the data has been collected:
//These, however, will error out when I try to set the null values.
myObject.setMilage(x1);
myObject.setColor(x2);
myObject.setName(x3);
}
It uses accessor methods which will pull the data from the passed object and then tries to set said values. In the above situation, it will throw a null pointer error as the milage and name are null; only the color is not.
My goal is to update the database with ONLY the values that have been set. In this case, I COULD write a ton of if/ else or try/ catch statements for every single one, that would work, but I would prefer not to.
Is there a shorter way to do this in Java? Is there a method where you can ONLY set data if it is not-null other than if/ else, try/catch, and going through every single setter method and telling it to skip null values?
EDIT: Just to clarify, the Nullpointerexception will get thrown on when it tries to set a null value. IE
myObject.setMilage(x1);
since people we asking.
Reflection is your answer. You may also try using some libraries making it a little more convenient (e.g. commons-beanutils).
So you may do something like:
private void copyIfSpecified(final Car from, final NewObject to, final String propName)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
final Object value = PropertyUtils.getSimpleProperty(from, propName);
if (value != null) {
PropertyUtils.setSimpleProperty(to, propName, value);
}
}
and call it from your method:
public void updateDatabasePrep(Car carObject){
NewObject myObject = new NewObject(); //Initialized, but empty
try {
copyIfSpecified(carObject, myObject, "milage");
copyIfSpecified(carObject, myObject, "color");
copyIfSpecified(carObject, myObject, "name");
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
throw new RuntimeException("Error while populating fields", ex);
}
}
This way you explicitly specify the properties to copy but avoid excessive if statements. In case you don't have to make sure all the fields you want are always copied (e.g. the fieldset is fixed and don't tend to be changed over time) you can do the whole copy thing via reflection (i.e. get all fields of the source object and copy non-null values to the destination object's fields - see PropertyUtils.copyProperties(..)
implementation).
ps: note that using this method applies additional restrictions to your classes (Car
and NewObject
) - they should be java beans: see What is a JavaBean exactly?
pps: and also note that using reflection takes A LOT more time than plain if-statements boilerplate - if you need performance you should think twice.