mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-12-21 23:08:52 -05:00
Add constructor calling for jdbcmapper and discover bug in javac 1.8 with -parameters option
This commit is contained in:
parent
d2df6dabaf
commit
df2ccda9fa
@ -49,7 +49,8 @@ public class CompileTimeRowToObjectMapper {
|
||||
protected final boolean returnMap, resultSetConstructor;
|
||||
|
||||
protected Element[] _fields = null;
|
||||
protected int[] _fieldTypes;
|
||||
protected int[] _fieldTypes, _fieldOrder;
|
||||
protected String[] _fieldClasses;
|
||||
|
||||
protected final ReflectionFields reflectionFields;
|
||||
|
||||
@ -78,21 +79,62 @@ public class CompileTimeRowToObjectMapper {
|
||||
componentType = returnTypeClass.getKind() == TypeKind.ARRAY ? ((ArrayType) returnTypeClass).getComponentType() : null;
|
||||
|
||||
// detect if returnTypeClass has a constructor that takes a ResultSet, if so, our job couldn't be easier...
|
||||
boolean resultSetConstructor = false, defaultConstructor = false;
|
||||
boolean resultSetConstructor = false, defaultConstructor = false, paramConstructor = false;
|
||||
if(_returnTypeClass.getKind() == TypeKind.DECLARED) {
|
||||
Map<String, Integer> strippedKeys = null;
|
||||
final List<? extends Element> methodsAndConstructors = ((TypeElement)((DeclaredType)_returnTypeClass).asElement()).getEnclosedElements();
|
||||
|
||||
/*
|
||||
// uncomment this to show difference between java 1.8 with -parameters and not, prints this without -parameters (javac 1.6 gets this correct also):
|
||||
// methodsAndConstructors: FieldPerson(): '', FieldPerson(long,java.util.Date,java.lang.String,java.lang.String): 'long PERSONNO, java.util.Date BIRTHDATE, java.lang.String FIRSTNAME, java.lang.String LASTNAME', FieldPerson(com.moparisthebest.jdbc.dto.Person): 'com.moparisthebest.jdbc.dto.Person PERSON'
|
||||
// but javac 1.8 prints this with -parameters (wrongly):
|
||||
// methodsAndConstructors: FieldPerson(): '', FieldPerson(long,java.util.Date,java.lang.String,java.lang.String): 'long PERSONNO, java.util.Date FIRSTNAME, java.lang.String LASTNAME, java.lang.String ARG3', FieldPerson(com.moparisthebest.jdbc.dto.Person): 'com.moparisthebest.jdbc.dto.Person PERSON'
|
||||
if(_returnTypeClass.toString().equals("com.moparisthebest.jdbc.dto.FieldPerson"))
|
||||
throw new RuntimeException("methodsAndConstructors: " + methodsAndConstructors.stream().filter(e -> e.getKind() == ElementKind.CONSTRUCTOR && e.getModifiers().contains(Modifier.PUBLIC)).map(e -> e.toString() +
|
||||
": '" + ((ExecutableElement)e).getParameters().stream().map(param -> param.asType() + " " + param.getSimpleName().toString().toUpperCase()).collect(java.util.stream.Collectors.joining(", ")) + "'"
|
||||
).collect(java.util.stream.Collectors.joining(", ")));
|
||||
*/
|
||||
outer:
|
||||
for(final Element e : methodsAndConstructors) {
|
||||
if(e.getKind() == ElementKind.CONSTRUCTOR) {
|
||||
if(e.getKind() == ElementKind.CONSTRUCTOR && e.getModifiers().contains(Modifier.PUBLIC)) {
|
||||
final List<? extends VariableElement> params = ((ExecutableElement)e).getParameters();
|
||||
if(params.isEmpty())
|
||||
defaultConstructor = true;
|
||||
else if(params.size() == 1 && rsm.types.isSameType(params.get(0).asType(), rsm.resultSetType))
|
||||
resultSetConstructor = true;
|
||||
else if(params.size() == _columnCount) {
|
||||
// maybe we want to call the constructor, if the names line up
|
||||
if(strippedKeys == null) {
|
||||
strippedKeys = new HashMap<String, Integer>(keys.length * 2);
|
||||
for (int x = 1; x <= _columnCount; ++x) {
|
||||
final String key = keys[x];
|
||||
strippedKeys.put(key, x);
|
||||
strippedKeys.put(key.replaceAll("_", ""), x);
|
||||
}
|
||||
_fieldOrder = new int[keys.length];
|
||||
_fieldTypes = new int[keys.length];
|
||||
_fieldClasses = new String[keys.length];
|
||||
}
|
||||
int count = 0;
|
||||
for(final VariableElement param : params) {
|
||||
final Integer index = strippedKeys.get(param.getSimpleName().toString().toUpperCase());
|
||||
if(index == null)
|
||||
continue outer;
|
||||
_fieldOrder[++count] = index;
|
||||
_fieldTypes[count] = getTypeId(param.asType());
|
||||
if(_fieldTypes[count] == TypeMappingsFactory.TYPE_ENUM) {
|
||||
_fieldClasses[count] = param.asType().toString();
|
||||
}
|
||||
}
|
||||
paramConstructor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!paramConstructor)
|
||||
_fieldOrder = null; // didn't successfully finish
|
||||
this.resultSetConstructor = resultSetConstructor;
|
||||
if(!resultSetConstructor && !defaultConstructor && _columnCount > 2 && componentType == null)
|
||||
if(!resultSetConstructor && !defaultConstructor && !paramConstructor && _columnCount > 2 && componentType == null)
|
||||
throw new RuntimeException("Exception when trying to get constructor for : "+_returnTypeClass.toString() + " Must have default no-arg constructor or one that takes a single ResultSet.");
|
||||
}
|
||||
}
|
||||
@ -270,6 +312,17 @@ public class CompileTimeRowToObjectMapper {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_fieldOrder != null) {
|
||||
java.append("final ").append(tType).append(" ret = new ").append(tType).append("(\n");
|
||||
for(int x = 1; x <= _columnCount; ++x) {
|
||||
extractColumnValueString(java, _fieldOrder[x], _fieldTypes[x], _fieldClasses[x]);
|
||||
if(x != _columnCount)
|
||||
java.append(",\n");
|
||||
}
|
||||
java.append(");\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (returnMap) // we want a map
|
||||
try {
|
||||
java.append("final ").append(tType).append("<String, Object> ret = new ").append(tType).append("<String, Object>();\n");
|
||||
|
@ -44,12 +44,12 @@ public interface PersonDAO extends Closeable {
|
||||
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
|
||||
String getFirstName(long personNo) throws SQLException;
|
||||
|
||||
@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(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, birth_date FROM person WHERE person_no = {personNo}")
|
||||
FieldPerson getPerson(long personNo, Calendar cal) throws SQLException;
|
||||
|
||||
@JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE last_name = {lastName}")
|
||||
List<FieldPerson> getPeople(String lastName) throws SQLException;
|
||||
|
||||
|
@ -191,7 +191,8 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
|
||||
}
|
||||
}
|
||||
//IFJAVA8_END
|
||||
if(constructor == null)
|
||||
if(constructor == null) {
|
||||
_fieldOrder = null; // we didn't complete this...
|
||||
try {
|
||||
constructor = _returnTypeClass.getDeclaredConstructor();
|
||||
if (!constructor.isAccessible())
|
||||
@ -199,9 +200,10 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
|
||||
} catch (Throwable e1) {
|
||||
// if column count is 2 or less, it might map directly to a type like a Long or something, or be a map which does
|
||||
// or if componentType is non-null, then we want an array like Long[] or String[]
|
||||
if(_columnCount > 2 && componentType == null)
|
||||
throw new MapperException("Exception when trying to get constructor for : "+_returnTypeClass.getName() + " Must have default no-arg constructor or one that takes a single ResultSet.", e1);
|
||||
if (_columnCount > 2 && componentType == null)
|
||||
throw new MapperException("Exception when trying to get constructor for : " + _returnTypeClass.getName() + " Must have default no-arg constructor or one that takes a single ResultSet.", e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.resultSetConstructor = resultSetConstructor;
|
||||
this.constructor = constructor;
|
||||
|
Loading…
Reference in New Issue
Block a user