mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-11-30 20:52:22 -05:00
Call super(Connection) if it exists, tweak cannot find Constructor error message
This commit is contained in:
parent
50ebcc84cb
commit
f68fd749e3
@ -2,6 +2,7 @@ package com.moparisthebest.jdbc.codegen;
|
|||||||
|
|
||||||
import com.moparisthebest.jdbc.CompilingRowToObjectMapper;
|
import com.moparisthebest.jdbc.CompilingRowToObjectMapper;
|
||||||
import com.moparisthebest.jdbc.MapperException;
|
import com.moparisthebest.jdbc.MapperException;
|
||||||
|
import com.moparisthebest.jdbc.RowToObjectMapper;
|
||||||
import com.moparisthebest.jdbc.TypeMappingsFactory;
|
import com.moparisthebest.jdbc.TypeMappingsFactory;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
@ -95,7 +96,7 @@ public class CompileTimeRowToObjectMapper {
|
|||||||
*/
|
*/
|
||||||
outer:
|
outer:
|
||||||
for(final Element e : methodsAndConstructors) {
|
for(final Element e : methodsAndConstructors) {
|
||||||
if(e.getKind() == ElementKind.CONSTRUCTOR && e.getModifiers().contains(Modifier.PUBLIC)) {
|
if(e.getKind() == ElementKind.CONSTRUCTOR && e.getModifiers().contains(Modifier.PUBLIC)) { // todo: public normally, but also package-private if same package, or protected if it's a sub-class of super...
|
||||||
final List<? extends VariableElement> params = ((ExecutableElement)e).getParameters();
|
final List<? extends VariableElement> params = ((ExecutableElement)e).getParameters();
|
||||||
if(params.isEmpty())
|
if(params.isEmpty())
|
||||||
defaultConstructor = true;
|
defaultConstructor = true;
|
||||||
@ -134,7 +135,8 @@ public class CompileTimeRowToObjectMapper {
|
|||||||
_fieldOrder = null; // didn't successfully finish
|
_fieldOrder = null; // didn't successfully finish
|
||||||
this.resultSetConstructor = resultSetConstructor;
|
this.resultSetConstructor = resultSetConstructor;
|
||||||
if(!resultSetConstructor && !defaultConstructor && !paramConstructor && _columnCount > 2 && componentType == null)
|
if(!resultSetConstructor && !defaultConstructor && !paramConstructor && _columnCount > 2 && componentType == null)
|
||||||
throw new MapperException("Exception when trying to get constructor for : "+_returnTypeClass.toString() + " Must have default no-arg constructor or one that takes a single ResultSet.");
|
throw new MapperException("Exception when trying to get constructor for : "+_returnTypeClass.toString() + " Must have default no-arg constructor, one that takes a single ResultSet, or one that takes parameters named like the query columns (in any order):\n" +
|
||||||
|
RowToObjectMapper.keysToString(keys)+ "\nRequires compilation with -parameters argument if source isn't being compiled this pass, beware Bug ID: JDK-8191074 with jdk8, fixed in 9+");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import javax.tools.Diagnostic;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.sql.Blob;
|
import java.sql.Blob;
|
||||||
import java.sql.Clob;
|
import java.sql.Clob;
|
||||||
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -65,7 +66,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
return messager;
|
return messager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType, jdbcMapperType,
|
static TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType, connectionType, jdbcMapperType,
|
||||||
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType, calendarType, cleanerType, enumType;
|
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType, calendarType, cleanerType, enumType;
|
||||||
//IFJAVA8_START
|
//IFJAVA8_START
|
||||||
static TypeMirror instantType, localDateTimeType, localDateType, localTimeType, zonedDateTimeType, offsetDateTimeType, offsetTimeType;
|
static TypeMirror instantType, localDateTimeType, localDateType, localTimeType, zonedDateTimeType, offsetDateTimeType, offsetTimeType;
|
||||||
@ -97,6 +98,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
utilDateType = elements.getTypeElement(java.util.Date.class.getCanonicalName()).asType();
|
utilDateType = elements.getTypeElement(java.util.Date.class.getCanonicalName()).asType();
|
||||||
readerType = elements.getTypeElement(Reader.class.getCanonicalName()).asType();
|
readerType = elements.getTypeElement(Reader.class.getCanonicalName()).asType();
|
||||||
clobType = elements.getTypeElement(Clob.class.getCanonicalName()).asType();
|
clobType = elements.getTypeElement(Clob.class.getCanonicalName()).asType();
|
||||||
|
connectionType = elements.getTypeElement(Connection.class.getCanonicalName()).asType();
|
||||||
jdbcMapperType = elements.getTypeElement(JdbcMapper.class.getCanonicalName()).asType();
|
jdbcMapperType = elements.getTypeElement(JdbcMapper.class.getCanonicalName()).asType();
|
||||||
inputStreamType = elements.getTypeElement(InputStream.class.getCanonicalName()).asType();
|
inputStreamType = elements.getTypeElement(InputStream.class.getCanonicalName()).asType();
|
||||||
fileType = elements.getTypeElement(File.class.getCanonicalName()).asType();
|
fileType = elements.getTypeElement(File.class.getCanonicalName()).asType();
|
||||||
@ -234,10 +236,19 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
w.write(className);
|
w.write(className);
|
||||||
w.write("() throws SQLException {\n\t\tthis(_conFactory);\n\t}\n");
|
w.write("() throws SQLException {\n\t\tthis(_conFactory);\n\t}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.write("\n\tprivate ");
|
||||||
|
w.write(className);
|
||||||
|
w.write("(final Connection conn, final boolean closeConn) {\n");
|
||||||
|
if(hasSuperConstructorTakesConnection(genClass))
|
||||||
|
w.write("\t\tsuper(conn);\n");
|
||||||
|
w.write("\t\tthis.conn = conn;\n\t\tthis.closeConn = closeConn;\n\t\tif (this.conn == null)\n" +
|
||||||
|
"\t\t\tthrow new NullPointerException(\"Connection needs to be non-null for JdbcMapper...\");\n\t}\n"
|
||||||
|
);
|
||||||
|
|
||||||
w.write("\n\tpublic ");
|
w.write("\n\tpublic ");
|
||||||
w.write(className);
|
w.write(className);
|
||||||
w.write("(Connection conn) {\n\t\tthis.conn = conn;\n\t\tthis.closeConn = false;\n\t\tif (this.conn == null)\n" +
|
w.write("(Connection conn) {\n\t\tthis(conn, false);\n\t}\n" +
|
||||||
"\t\t\tthrow new NullPointerException(\"Connection needs to be non-null for JdbcMapper...\");\n\t}\n" +
|
|
||||||
"\n\tpublic Connection getConnection() {\n\t\treturn this.conn;\n\t}\n"
|
"\n\tpublic Connection getConnection() {\n\t\treturn this.conn;\n\t}\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -541,8 +552,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
// and we can create constructors that set closeConn to true!
|
// and we can create constructors that set closeConn to true!
|
||||||
w.write("\n\tpublic ");
|
w.write("\n\tpublic ");
|
||||||
w.write(className);
|
w.write(className);
|
||||||
w.write("(final Factory<Connection> connectionFactory) throws SQLException {\n\t\tthis.conn = connectionFactory.create();\n\t\tthis.closeConn = true;\n\t\tif (this.conn == null)\n" +
|
w.write("(final Factory<Connection> connectionFactory) throws SQLException {\n\t\tthis(connectionFactory.create(), true);\n\t}\n"
|
||||||
"\t\t\tthrow new NullPointerException(\"Connection needs to be non-null for JdbcMapper...\");\n\t}\n"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
w.write("\n\tpublic ");
|
w.write("\n\tpublic ");
|
||||||
@ -950,4 +960,16 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
tryClose(pw);
|
tryClose(pw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasSuperConstructorTakesConnection(final TypeElement genClass) {
|
||||||
|
final List<? extends Element> methodsAndConstructors = genClass.getEnclosedElements();
|
||||||
|
for(final Element e : methodsAndConstructors) {
|
||||||
|
if (e.getKind() == ElementKind.CONSTRUCTOR && !e.getModifiers().contains(Modifier.PRIVATE)) {
|
||||||
|
final List<? extends VariableElement> params = ((ExecutableElement)e).getParameters();
|
||||||
|
if(params.size() == 1 && types.isSameType(params.get(0).asType(), connectionType))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,11 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
|
|||||||
// 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
|
// 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[]
|
// or if componentType is non-null, then we want an array like Long[] or String[]
|
||||||
if (_columnCount > 2 && componentType == null)
|
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);
|
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"
|
||||||
|
//IFJAVA8_START
|
||||||
|
+ ", or one that takes parameters named like the query columns (in any order):\n" + keysToString(keys) + "\nRequires compilation with -parameters argument, beware Bug ID: JDK-8191074 with jdk8, fixed in 9+"
|
||||||
|
//IFJAVA8_END
|
||||||
|
, e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,6 +212,24 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
|
|||||||
this.constructorLoaded = true;
|
this.constructorLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String keysToString(final String[] a) {
|
||||||
|
if (a == null)
|
||||||
|
return "null";
|
||||||
|
|
||||||
|
int iMax = a.length - 1;
|
||||||
|
if (iMax == 0)
|
||||||
|
return "[]";
|
||||||
|
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append('[');
|
||||||
|
for (int i = 1; ; i++) {
|
||||||
|
b.append(String.valueOf(a[i]));
|
||||||
|
if (i == iMax)
|
||||||
|
return b.append(']').toString();
|
||||||
|
b.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This returns a new instance of the Map class required by Map<String, Object>[]
|
* This returns a new instance of the Map class required by Map<String, Object>[]
|
||||||
* It lives in it's own method to minimize suppressed warnings and allow subclasses to override methods,
|
* It lives in it's own method to minimize suppressed warnings and allow subclasses to override methods,
|
||||||
|
@ -118,5 +118,6 @@ try(QueryMapper qm = new QueryMapper("java:/comp/env/jdbc/testPool", new ResultS
|
|||||||
TODO
|
TODO
|
||||||
----
|
----
|
||||||
|
|
||||||
* Binding of Enum to String by default
|
* DOCUMENTATION!!!!!
|
||||||
* sql other than select return boolean, int > 0 ?
|
* sql other than select return boolean, int > 0 ?
|
||||||
|
* @RunInTransaction void support
|
Loading…
Reference in New Issue
Block a user