From 46686e5b0539ae0d0b4752436b092011ec4007cf Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Mon, 19 Jun 2017 00:34:23 -0400 Subject: [PATCH] Allow JdbcMapper to use reflection for non-public fields optionally --- .../jdbc/codegen/JdbcMapper.java | 10 +++ .../codegen/CompileTimeResultSetMapper.java | 76 +++++++++---------- .../codegen/CompileTimeRowToObjectMapper.java | 20 +++-- .../jdbc/codegen/JdbcMapperProcessor.java | 16 +++- .../jdbc/codegen/ReflectionFields.java | 30 ++++++++ .../jdbc/codegen/JdbcMapperTest.java | 5 ++ .../jdbc/codegen/PersonDAO.java | 3 +- .../jdbc/codegen/PrestoPersonDAO.java | 3 +- .../CleaningCompilingResultSetMapper.java | 6 +- .../jdbc/CompilingRowToObjectMapper.java | 1 - .../jdbc/CleaningQueryMapperTest.java | 2 +- .../moparisthebest/jdbc/dto/FieldPerson.java | 4 +- 12 files changed, 123 insertions(+), 53 deletions(-) create mode 100644 jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/ReflectionFields.java diff --git a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java index 0c05c8e..39f3bb0 100644 --- a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java +++ b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java @@ -36,6 +36,11 @@ public interface JdbcMapper extends Closeable { */ Class sqlParser() default SQLParser.class; + /** + * This defaults to false + */ + OptionalBool allowReflection() default OptionalBool.DEFAULT; + /** * This defaults to SimpleSQLParser, PrestoSQLParser is another option for Java 8, or implement your own * @return @@ -58,6 +63,11 @@ public interface JdbcMapper extends Closeable { */ OptionalBool cachePreparedStatement() default OptionalBool.DEFAULT; + /** + * This defaults to the value of the class-level @JdbcMapper.Mapper.allowReflection annotation, but can be configured on a per-method level here + */ + OptionalBool allowReflection() default OptionalBool.DEFAULT; + /** * Maximum rows returned in collections/maps/arrays/etc, < 1 mean no limit * diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeResultSetMapper.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeResultSetMapper.java index 7984f90..60ee68b 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeResultSetMapper.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeResultSetMapper.java @@ -90,17 +90,17 @@ public class CompileTimeResultSetMapper { * * @return true if calling code should close rs (ResultSet) and ps (PreparedStatement) if closePs is false, false otherwise */ - public boolean mapToResultType(final Writer w, final String[] keys, final ExecutableElement eeMethod, final MaxRows maxRows, final String cal, final String cleaner, final boolean closePs) throws IOException, NoSuchMethodException, ClassNotFoundException { + public boolean mapToResultType(final Writer w, final String[] keys, final ExecutableElement eeMethod, final MaxRows maxRows, final String cal, final String cleaner, final boolean closePs, final ReflectionFields reflectionFields) throws IOException, NoSuchMethodException, ClassNotFoundException { //final Method m = fromExecutableElement(eeMethod); //final Class returnType = m.getReturnType(); final TypeMirror returnTypeMirror = eeMethod.getReturnType(); //final Class returnType = typeMirrorToClass(returnTypeMirror); if (returnTypeMirror.getKind() == TypeKind.ARRAY) { final TypeMirror componentType = ((ArrayType) returnTypeMirror).getComponentType(); - toArray(w, keys, componentType, maxRows, cal, cleaner); + toArray(w, keys, componentType, maxRows, cal, cleaner, reflectionFields); } else if (types.isAssignable(returnTypeMirror, collectionType)) { final List typeArguments = ((DeclaredType) returnTypeMirror).getTypeArguments(); - toCollection(w, keys, returnTypeMirror, typeArguments.get(0), maxRows, cal, cleaner); + toCollection(w, keys, returnTypeMirror, typeArguments.get(0), maxRows, cal, cleaner, reflectionFields); } else if (types.isAssignable(returnTypeMirror, mapType)) { final List typeArguments = ((DeclaredType) returnTypeMirror).getTypeArguments(); //if (types[1] instanceof ParameterizedType) { // for collectionMaps @@ -112,57 +112,57 @@ public class CompileTimeResultSetMapper { typeArguments.get(0), collectionTypeMirror, componentTypeMirror, - maxRows, cal, cleaner); + maxRows, cal, cleaner, reflectionFields); return true; } - toMap(w, keys, returnTypeMirror, typeArguments.get(0), typeArguments.get(1), maxRows, cal, cleaner); + toMap(w, keys, returnTypeMirror, typeArguments.get(0), typeArguments.get(1), maxRows, cal, cleaner, reflectionFields); } else if (types.isAssignable(returnTypeMirror, iteratorType)) { final List typeArguments = ((DeclaredType) returnTypeMirror).getTypeArguments(); if (types.isAssignable(returnTypeMirror, resultSetIterableType)) { - toResultSetIterable(w, keys, typeArguments.get(0), cal, cleaner, closePs); + toResultSetIterable(w, keys, typeArguments.get(0), cal, cleaner, closePs, reflectionFields); return false; } else if (types.isAssignable(returnTypeMirror, listIteratorType)) - toListIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner); + toListIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner, reflectionFields); else - toIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner); + toIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner, reflectionFields); } //IFJAVA8_START else if (types.isAssignable(returnTypeMirror, streamType)) { - toStream(w, keys, ((DeclaredType) returnTypeMirror).getTypeArguments().get(0), cal, cleaner, closePs); + toStream(w, keys, ((DeclaredType) returnTypeMirror).getTypeArguments().get(0), cal, cleaner, closePs, reflectionFields); return false; } //IFJAVA8_END else { - toObject(w, keys, returnTypeMirror, cal, cleaner); + toObject(w, keys, returnTypeMirror, cal, cleaner, reflectionFields); } return true; } - public CompileTimeRowToObjectMapper getRowMapper(final String[] keys, TypeMirror returnTypeClass, String cal, TypeMirror mapValType, TypeMirror mapKeyType) { - return getRowMapper(keys, returnTypeClass, "rs", cal, mapValType, mapKeyType); + public CompileTimeRowToObjectMapper getRowMapper(final String[] keys, TypeMirror returnTypeClass, String cal, TypeMirror mapValType, TypeMirror mapKeyType, final ReflectionFields reflectionFields) { + return getRowMapper(keys, returnTypeClass, "rs", cal, mapValType, mapKeyType, reflectionFields); } - public CompileTimeRowToObjectMapper getRowMapper(final String[] keys, TypeMirror returnTypeClass, final String resultSetName, String cal, TypeMirror mapValType, TypeMirror mapKeyType) { - return new CompileTimeRowToObjectMapper(this, keys, returnTypeClass, resultSetName, cal, mapValType, mapKeyType); + public CompileTimeRowToObjectMapper getRowMapper(final String[] keys, TypeMirror returnTypeClass, final String resultSetName, String cal, TypeMirror mapValType, TypeMirror mapKeyType, final ReflectionFields reflectionFields) { + return new CompileTimeRowToObjectMapper(this, keys, returnTypeClass, resultSetName, cal, mapValType, mapKeyType, reflectionFields); } - public void writeObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal) throws IOException, ClassNotFoundException { - writeObject(w, keys, returnTypeMirror, "rs", cal); + public void writeObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { + writeObject(w, keys, returnTypeMirror, "rs", cal, reflectionFields); } - public void writeObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String resultSetName, final String cal) throws IOException, ClassNotFoundException { - getRowMapper(keys, returnTypeMirror, resultSetName, cal, null, null).gen(w, returnTypeMirror.toString()); + public void writeObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String resultSetName, final String cal, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { + getRowMapper(keys, returnTypeMirror, resultSetName, cal, null, null, reflectionFields).gen(w, returnTypeMirror.toString()); } - public void toObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toObject(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { w.write("\t\t\tif(rs.next()) {\n"); - writeObject(w, keys, returnTypeMirror, cal); + writeObject(w, keys, returnTypeMirror, cal, reflectionFields); w.write("\t\t\t\treturn "); // this does not clean null on purpose, neither does CleaningResultSetMapper clean(w, cleaner).write(";\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n"); } - private void toResultSetIterable(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner, final boolean closePs) throws IOException, ClassNotFoundException { + private void toResultSetIterable(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner, final boolean closePs, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { w.write("\t\t\treturn com.moparisthebest.jdbc.util.ResultSetIterable.getResultSetIterable(rs,\n\t\t\t\t\trs.next() ? "); if(java8) { @@ -175,7 +175,7 @@ public class CompileTimeResultSetMapper { } // com.moparisthebest.jdbc.util.ResultSetToObject implementation - writeObject(w, keys, returnTypeMirror, "_rs", cal == null ? null : "_cal"); + writeObject(w, keys, returnTypeMirror, "_rs", cal == null ? null : "_cal", reflectionFields); w.write("\t\t\t\t\t\treturn "); clean(w, cleaner).write(";\n"); // end ResultSetToObject implementation @@ -192,7 +192,7 @@ public class CompileTimeResultSetMapper { //IFJAVA8_START // being in this method implies java8 is true already, how else could you be compiling code using Stream? so this won't have the checks for lambdas toResultSetIterable does... - private void toStream(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner, final boolean closePs) throws IOException, ClassNotFoundException { + private void toStream(final Writer w, final String[] keys, final TypeMirror returnTypeMirror, final String cal, final String cleaner, final boolean closePs, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { if(closePs) w.write("\t\t\tfinal PreparedStatement finalPs = ps;\n"); @@ -202,7 +202,7 @@ public class CompileTimeResultSetMapper { w.append("(_rs, _cal) -> {\n"); // com.moparisthebest.jdbc.util.ResultSetToObject implementation - writeObject(w, keys, returnTypeMirror, "_rs", cal == null ? null : "_cal"); + writeObject(w, keys, returnTypeMirror, "_rs", cal == null ? null : "_cal", reflectionFields); w.write("\t\t\t\t\t\treturn "); clean(w, cleaner).write(";\n"); // end ResultSetToObject implementation @@ -215,46 +215,46 @@ public class CompileTimeResultSetMapper { //IFJAVA8_END - public void writeCollection(final Writer w, final String[] keys, final String returnTypeString, final String concreteTypeString, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void writeCollection(final Writer w, final String[] keys, final String returnTypeString, final String concreteTypeString, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { maxRowInit(w, maxRows).write("\t\t\tfinal "); w.write(returnTypeString); w.write(" _colret = new "); w.write(concreteTypeString); w.write(returnTypeString.substring(returnTypeString.indexOf('<'))); w.write("();\n\t\t\twhile(rs.next()) {\n"); - writeObject(w, keys, componentTypeMirror, cal); + writeObject(w, keys, componentTypeMirror, cal, reflectionFields); w.write("\t\t\t\t_colret.add("); clean(w, cleaner).write(");\n"); maxRowBreak(w, maxRows).write("\t\t\t}\n"); } - public void toCollection(final Writer w, final String[] keys, final TypeMirror collectionTypeMirror, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toCollection(final Writer w, final String[] keys, final TypeMirror collectionTypeMirror, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String collectionType = getConcreteClassCanonicalName(collectionTypeMirror, ArrayList.class); - writeCollection(w, keys, collectionTypeMirror.toString(), collectionType, componentTypeMirror, maxRows, cal, cleaner); + writeCollection(w, keys, collectionTypeMirror.toString(), collectionType, componentTypeMirror, maxRows, cal, cleaner, reflectionFields); w.write("\t\t\treturn _colret;\n"); } - public void toArray(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toArray(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String returnTypeString = componentTypeMirror.toString(); - writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner); + writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner, reflectionFields); w.write("\t\t\treturn _colret.toArray(new "); w.write(returnTypeString); w.write("[_colret.size()]);\n"); } - public void toListIterator(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toListIterator(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String returnTypeString = componentTypeMirror.toString(); - writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner); + writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner, reflectionFields); w.write("\t\t\treturn _colret.listIterator();\n"); } - public void toIterator(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toIterator(final Writer w, final String[] keys, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String returnTypeString = componentTypeMirror.toString(); - writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner); + writeCollection(w, keys, "java.util.List<" + returnTypeString + ">", "java.util.ArrayList", componentTypeMirror, maxRows, cal, cleaner, reflectionFields); w.write("\t\t\treturn _colret.iterator();\n"); } - public void toMap(final Writer w, final String[] keys, final TypeMirror mapTypeMirror, final TypeMirror mapKeyTypeMirror, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + public void toMap(final Writer w, final String[] keys, final TypeMirror mapTypeMirror, final TypeMirror mapKeyTypeMirror, final TypeMirror componentTypeMirror, MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String mapType = getConcreteClassCanonicalName(mapTypeMirror, HashMap.class); final String returnTypeString = mapTypeMirror.toString(); maxRowInit(w, maxRows).write("\t\t\tfinal "); @@ -265,7 +265,7 @@ public class CompileTimeResultSetMapper { w.write("();\n\t\t\twhile(rs.next()) {\n"); //writeObject(w, keys, componentTypeMirror, componentType, cal); - final CompileTimeRowToObjectMapper rm = getRowMapper(keys, componentTypeMirror, cal, null, mapKeyTypeMirror); + final CompileTimeRowToObjectMapper rm = getRowMapper(keys, componentTypeMirror, cal, null, mapKeyTypeMirror, reflectionFields); rm.gen(w, componentTypeMirror.toString()); w.write("\t\t\t\t_colret.put("); rm.extractColumnValueString(w, 1, mapKeyTypeMirror); @@ -280,7 +280,7 @@ public class CompileTimeResultSetMapper { final TypeMirror mapKeyTypeMirror, final TypeMirror collectionTypeMirror, final TypeMirror componentTypeMirror, - MaxRows maxRows, String cal, final String cleaner) throws IOException, ClassNotFoundException { + MaxRows maxRows, String cal, final String cleaner, final ReflectionFields reflectionFields) throws IOException, ClassNotFoundException { final String mapType = getConcreteClassCanonicalName(mapTypeMirror, HashMap.class); final String collectionType = getConcreteClassCanonicalName(collectionTypeMirror, ArrayList.class); final String returnTypeString = mapTypeMirror.toString(); @@ -294,7 +294,7 @@ public class CompileTimeResultSetMapper { w.write("();\n\t\t\twhile(rs.next()) {\n"); //writeObject(w, keys, componentTypeMirror, componentType, cal); - final CompileTimeRowToObjectMapper rm = getRowMapper(keys, componentTypeMirror, cal, null, mapKeyTypeMirror); + final CompileTimeRowToObjectMapper rm = getRowMapper(keys, componentTypeMirror, cal, null, mapKeyTypeMirror, reflectionFields); rm.gen(w, componentTypeMirror.toString()); w.write("\t\t\t\tfinal "); diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java index 89a3c32..5180977 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java @@ -51,9 +51,12 @@ public class CompileTimeRowToObjectMapper { protected Element[] _fields = null; protected int[] _fieldTypes; - public CompileTimeRowToObjectMapper(final CompileTimeResultSetMapper rsm, final String[] keys, final TypeMirror returnTypeClass, final String resultSetName, final String calendarName, final TypeMirror mapValType, final TypeMirror mapKeyType) { + protected final ReflectionFields reflectionFields; + + public CompileTimeRowToObjectMapper(final CompileTimeResultSetMapper rsm, final String[] keys, final TypeMirror returnTypeClass, final String resultSetName, final String calendarName, final TypeMirror mapValType, final TypeMirror mapKeyType, final ReflectionFields reflectionFields) { this.rsm = rsm; this.keys = keys; + this.reflectionFields = reflectionFields; _calendarName = calendarName; _resultSetName = resultSetName; @@ -176,7 +179,7 @@ public class CompileTimeRowToObjectMapper { final VariableElement f = (VariableElement)e; //System.out.println("f.fieldName: "+f.getSimpleName()); if (f.getModifiers().contains(Modifier.STATIC)) continue; - if (!f.getModifiers().contains(Modifier.PUBLIC)) continue; + //if (reflectionFields == null && !f.getModifiers().contains(Modifier.PUBLIC)) continue; String fieldName = f.getSimpleName().toString().toUpperCase(); //System.out.println("fieldName: "+fieldName); if (!mapFields.containsKey(fieldName)) { @@ -355,9 +358,16 @@ public class CompileTimeRowToObjectMapper { } if (isField) { // if f not accessible (but super.getFieldMappings() sets it), throw exception during compilation is fine - java.append("ret.").append(f.getSimpleName().toString()).append(" = "); - extractColumnValueString(java, i, _fieldTypes[i], enumName); - java.append(";\n"); + final Set mods = reflectionFields == null ? null : f.getModifiers(); + if(mods != null && (mods.contains(Modifier.PRIVATE) || mods.contains(Modifier.PROTECTED) || mods.contains(Modifier.FINAL))) { + java.append("com.moparisthebest.jdbc.util.ReflectionUtil.setValue(_fields[").append(String.valueOf((reflectionFields.addGetIndex((VariableElement)f)))).append("], ret, "); + extractColumnValueString(java, i, _fieldTypes[i], enumName); + java.append(");\n"); + } else { + java.append("ret.").append(f.getSimpleName().toString()).append(" = "); + extractColumnValueString(java, i, _fieldTypes[i], enumName); + java.append(";\n"); + } } else { java.append("ret.").append(f.getSimpleName().toString()).append("("); extractColumnValueString(java, i, _fieldTypes[i], enumName); diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java index 425624e..4d8c49a 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java @@ -200,6 +200,9 @@ public class JdbcMapperProcessor extends AbstractProcessor { lookupCloseMethod = false; } + final boolean defaultAllowReflection = mapper.allowReflection().combine(false); + final ReflectionFields reflectionFields = new ReflectionFields(); + for (final Element methodElement : genClass.getEnclosedElements()) { // can only implement abstract methods if (methodElement.getKind() != ElementKind.METHOD || !methodElement.getModifiers().contains(Modifier.ABSTRACT)) @@ -215,6 +218,7 @@ public class JdbcMapperProcessor extends AbstractProcessor { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL with non-empty query is required on abstract or interface methods", methodElement); continue; } + final boolean allowReflection = sql.allowReflection().combine(defaultAllowReflection); w.write("\n\t@Override\n\tpublic "); final String returnType = eeMethod.getReturnType().toString(); w.write(returnType); @@ -372,7 +376,7 @@ public class JdbcMapperProcessor extends AbstractProcessor { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL sql parsed a wildcard column name which is not supported", methodElement); return false; } - closeRs = rsm.mapToResultType(w, keys, eeMethod, maxRows, calendarName, cleanerName, !cachePreparedStatements); + closeRs = rsm.mapToResultType(w, keys, eeMethod, maxRows, calendarName, cleanerName, !cachePreparedStatements, allowReflection ? reflectionFields : null); } // close things @@ -412,6 +416,16 @@ public class JdbcMapperProcessor extends AbstractProcessor { continue; } + if(!reflectionFields.isEmpty()) { + w.append("\n\tprivate static final java.lang.reflect.Field[] _fields = new java.lang.reflect.Field[] {\n"); + for(final VariableElement ve : reflectionFields) { + w.append("\t\tcom.moparisthebest.jdbc.util.ReflectionUtil.getAccessibleField(") + .append(ve.getEnclosingElement().asType().toString()).append(".class, \"") + .append(ve.getSimpleName().toString()).append("\"),\n"); + } + w.append("\t};\n"); + } + if (cachedPreparedStatements > 0) { w.write("\n\tprivate final PreparedStatement[] psCache = new PreparedStatement["); w.write(Integer.toString(cachedPreparedStatements)); diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/ReflectionFields.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/ReflectionFields.java new file mode 100644 index 0000000..666d61f --- /dev/null +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/ReflectionFields.java @@ -0,0 +1,30 @@ +package com.moparisthebest.jdbc.codegen; + +import javax.lang.model.element.VariableElement; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by mopar on 6/19/17. + */ +public class ReflectionFields implements Iterable { + private final List fields = new ArrayList(); + + public int addGetIndex(final VariableElement ve) { + final int ret = fields.indexOf(ve); + if(ret != -1) + return ret; + fields.add(ve); + return fields.size() - 1; + } + + public boolean isEmpty() { + return fields.isEmpty(); + } + + @Override + public Iterator iterator() { + return fields.iterator(); + } +} diff --git a/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/JdbcMapperTest.java b/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/JdbcMapperTest.java index bbde352..beda834 100644 --- a/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/JdbcMapperTest.java +++ b/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/JdbcMapperTest.java @@ -189,4 +189,9 @@ public class JdbcMapperTest { } //IFJAVA8_END + + @Test + public void testPerson() throws SQLException { + assertEquals(fieldPerson1, dao.getPerson(fieldPerson1.getPersonNo())); + } } diff --git a/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/PersonDAO.java b/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/PersonDAO.java index f6509c9..921799d 100644 --- a/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/PersonDAO.java +++ b/jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/PersonDAO.java @@ -25,6 +25,7 @@ import java.time.*; // databaseType = JdbcMapper.DatabaseType.ORACLE cachePreparedStatements = JdbcMapper.OptionalBool.FALSE // , sqlParser = SimpleSQLParser.class + , allowReflection = JdbcMapper.OptionalBool.TRUE ) public interface PersonDAO extends Closeable { @@ -46,7 +47,7 @@ public interface PersonDAO extends Closeable { @JdbcMapper.SQL("SELECT first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") FieldPerson getPerson(long personNo, Calendar cal) throws SQLException; - @JdbcMapper.SQL("SELECT first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") + @JdbcMapper.SQL(value = "SELECT person_no, first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") FieldPerson getPerson(long personNo) throws SQLException; @JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE last_name = {lastName}") diff --git a/presto-sqlparser/src/test/java/com/moparisthebest/jdbc/codegen/PrestoPersonDAO.java b/presto-sqlparser/src/test/java/com/moparisthebest/jdbc/codegen/PrestoPersonDAO.java index 8543bc2..72f4421 100644 --- a/presto-sqlparser/src/test/java/com/moparisthebest/jdbc/codegen/PrestoPersonDAO.java +++ b/presto-sqlparser/src/test/java/com/moparisthebest/jdbc/codegen/PrestoPersonDAO.java @@ -25,6 +25,7 @@ import java.time.*; // databaseType = JdbcMapper.DatabaseType.ORACLE cachePreparedStatements = JdbcMapper.OptionalBool.FALSE , sqlParser = PrestoSQLParser.class + , allowReflection = JdbcMapper.OptionalBool.TRUE ) public interface PrestoPersonDAO extends PersonDAO { @@ -46,7 +47,7 @@ public interface PrestoPersonDAO extends PersonDAO { @JdbcMapper.SQL("SELECT first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") FieldPerson getPerson(long personNo, Calendar cal) throws SQLException; - @JdbcMapper.SQL("SELECT first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") + @JdbcMapper.SQL(value = "SELECT person_no, first_name, last_name, birth_date FROM person WHERE person_no = {personNo}") FieldPerson getPerson(long personNo) throws SQLException; @JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE last_name = {lastName}") diff --git a/querymapper/src/main/java/com/moparisthebest/jdbc/CleaningCompilingResultSetMapper.java b/querymapper/src/main/java/com/moparisthebest/jdbc/CleaningCompilingResultSetMapper.java index 340c763..c707647 100644 --- a/querymapper/src/main/java/com/moparisthebest/jdbc/CleaningCompilingResultSetMapper.java +++ b/querymapper/src/main/java/com/moparisthebest/jdbc/CleaningCompilingResultSetMapper.java @@ -11,17 +11,17 @@ public class CleaningCompilingResultSetMapper extends CompilingResultSetMappe private final Cleaner cleaner; - public CleaningCompilingResultSetMapper(final Calendar cal, final int arrayMaxLength, final CompilingRowToObjectMapper.Cache cache, final Cleaner cleaner) { + public CleaningCompilingResultSetMapper(final Cleaner cleaner, final Calendar cal, final int arrayMaxLength, final CompilingRowToObjectMapper.Cache cache) { super(cal, arrayMaxLength, cache); this.cleaner = cleaner; } - public CleaningCompilingResultSetMapper(final CompilingRowToObjectMapper.Cache cache, final Cleaner cleaner) { + public CleaningCompilingResultSetMapper(final Cleaner cleaner, final CompilingRowToObjectMapper.Cache cache) { super(cache); this.cleaner = cleaner; } - public CleaningCompilingResultSetMapper(final int arrayMaxLength, final CompilingRowToObjectMapper.Cache cache, final Cleaner cleaner) { + public CleaningCompilingResultSetMapper(final Cleaner cleaner, final int arrayMaxLength, final CompilingRowToObjectMapper.Cache cache) { super(arrayMaxLength, cache); this.cleaner = cleaner; } diff --git a/querymapper/src/main/java/com/moparisthebest/jdbc/CompilingRowToObjectMapper.java b/querymapper/src/main/java/com/moparisthebest/jdbc/CompilingRowToObjectMapper.java index b91d466..4a08f55 100644 --- a/querymapper/src/main/java/com/moparisthebest/jdbc/CompilingRowToObjectMapper.java +++ b/querymapper/src/main/java/com/moparisthebest/jdbc/CompilingRowToObjectMapper.java @@ -1,7 +1,6 @@ package com.moparisthebest.jdbc; import com.moparisthebest.classgen.Compiler; -import com.sun.org.apache.xpath.internal.operations.Mod; import java.io.IOException; import java.lang.reflect.AccessibleObject; diff --git a/querymapper/src/test/java/com/moparisthebest/jdbc/CleaningQueryMapperTest.java b/querymapper/src/test/java/com/moparisthebest/jdbc/CleaningQueryMapperTest.java index ca3cec3..80e451a 100644 --- a/querymapper/src/test/java/com/moparisthebest/jdbc/CleaningQueryMapperTest.java +++ b/querymapper/src/test/java/com/moparisthebest/jdbc/CleaningQueryMapperTest.java @@ -65,7 +65,7 @@ public class CleaningQueryMapperTest { return Arrays.asList(new Object[][] { { new CleaningResultSetMapper(personCleaner) }, { new CleaningCachingResultSetMapper(personCleaner) }, - { new CleaningCompilingResultSetMapper(personCleaner) }, + { new CleaningCompilingResultSetMapper(personCleaner, new CompilingRowToObjectMapper.Cache(true)) }, }); } diff --git a/querymapper/src/test/java/com/moparisthebest/jdbc/dto/FieldPerson.java b/querymapper/src/test/java/com/moparisthebest/jdbc/dto/FieldPerson.java index 2798500..1299b5c 100644 --- a/querymapper/src/test/java/com/moparisthebest/jdbc/dto/FieldPerson.java +++ b/querymapper/src/test/java/com/moparisthebest/jdbc/dto/FieldPerson.java @@ -7,8 +7,8 @@ import java.util.Date; */ public class FieldPerson implements Person { - public long personNo; - public Date birthDate; + protected long personNo; + protected Date birthDate; public String firstName; public String lastName;