Skip to content

Instantly share code, notes, and snippets.

@tlehman
Last active June 27, 2018 17:02
Show Gist options
  • Save tlehman/bf60381413151871775c44cd8a9f934a to your computer and use it in GitHub Desktop.
Save tlehman/bf60381413151871775c44cd8a9f934a to your computer and use it in GitHub Desktop.
Build a SQL string from a Java object using reflection, and handling nulls gracefully
import lombok.Builder;
import lombok.Value;
@Builder
@Value
public class Address {
private String street1;
private String street2;
private String city;
private String cityCode;
private String district;
private String stateCode;
private String postalCode;
private String countryCode;
private String countryName;
private String regionName;
}
// Compile using:
// javac -cp lombok.jar Address.java
import java.util.List;
import java.util.LinkedList;
import java.util.Optional;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String[] args) {
Address address = Address.builder()
.street1("123 Wayland Ave")
.city("Gotham")
.postalCode("80113")
.countryName("The Sovereign Autonomous Region of Cascadia")
.build();
System.out.println(buildUpsertStatement(address));
}
private static String buildUpsertStatement(Object object) {
Field[] fields = object.getClass().getDeclaredFields();
List<String> pairs = new LinkedList<>();
try {
for(Field field: fields) {
String methodName = String.format("get%s%s",
field.getName().substring(0,1).toUpperCase(),
field.getName().substring(1));
Method method = object.getClass().getMethod(methodName);
String value = (String)method.invoke(object);
if(value != null) {
pairs.add(String.format("%s = '%s'", snake_caseify(field.getName()), value));
}
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return pairs.stream().collect(Collectors.joining(", "));
}
private static String snake_caseify(String camelCase) {
StringBuilder sb = new StringBuilder();
int offset = (int)'a' - (int)'A';
for(Character c: camelCase.toCharArray()) {
// if c is upper case
if((int)c >= (int)'A' && c <= (int)'Z') {
sb.append('_');
sb.append((char)((int)c + offset));
} else {
sb.append(c);
}
}
return sb.toString();
}
}
@tlehman
Copy link
Author

tlehman commented Jun 27, 2018

If you compile Address.java, then compile Main.java, the JVM classloader will load Address.class from the same directory. Note: make sure lombok.jar is in the same directory before compiling Address.

@tlehman
Copy link
Author

tlehman commented Jun 27, 2018

$ javac Main.java && java Main
street1 = '123 Wayland Ave', city = 'Gotham', postal_code = '80113', country_name = 'The Sovereign Autonomous Region of Cascadia'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment