mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-12-22 07:18:51 -05:00
Add ResultSetIterable support to jdbcmapper
This commit is contained in:
parent
d74c272e73
commit
881de93799
@ -2,6 +2,7 @@ package com.moparisthebest.jdbc.codegen;
|
||||
|
||||
import com.moparisthebest.jdbc.Finishable;
|
||||
import com.moparisthebest.jdbc.ResultSetMapper;
|
||||
import com.moparisthebest.jdbc.util.ResultSetIterable;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
@ -26,7 +27,8 @@ import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorToCl
|
||||
public class CompileTimeResultSetMapper {
|
||||
|
||||
public final Types types;
|
||||
public final TypeMirror collectionType, mapType, mapCollectionType, iteratorType, listIteratorType, finishableType, resultSetType;
|
||||
public final TypeMirror collectionType, mapType, mapCollectionType, iteratorType, listIteratorType, finishableType, resultSetType, resultSetIterableType;
|
||||
private final boolean java8 = false;
|
||||
|
||||
public CompileTimeResultSetMapper(final ProcessingEnvironment processingEnv) {
|
||||
types = processingEnv.getTypeUtils();
|
||||
@ -41,6 +43,8 @@ public class CompileTimeResultSetMapper {
|
||||
|
||||
finishableType = elements.getTypeElement(Finishable.class.getCanonicalName()).asType();
|
||||
resultSetType = elements.getTypeElement(ResultSet.class.getCanonicalName()).asType();
|
||||
|
||||
resultSetIterableType = types.getDeclaredType(elements.getTypeElement(ResultSetIterable.class.getCanonicalName()), types.getWildcardType(null, null));
|
||||
}
|
||||
|
||||
public static String getConcreteClassCanonicalName(final TypeMirror returnType, final Class defaultConcreteClass) {
|
||||
@ -56,7 +60,11 @@ public class CompileTimeResultSetMapper {
|
||||
return typeMirrorStringNoGenerics(returnType);
|
||||
}
|
||||
|
||||
public void mapToResultType(final Writer w, final String[] keys, final ExecutableElement eeMethod, final MaxRows maxRows, final String cal, final String cleaner) throws IOException, NoSuchMethodException, ClassNotFoundException {
|
||||
/**
|
||||
*
|
||||
* @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 {
|
||||
//final Method m = fromExecutableElement(eeMethod);
|
||||
//final Class returnType = m.getReturnType();
|
||||
final TypeMirror returnTypeMirror = eeMethod.getReturnType();
|
||||
@ -79,18 +87,22 @@ public class CompileTimeResultSetMapper {
|
||||
collectionTypeMirror,
|
||||
componentTypeMirror,
|
||||
maxRows, cal, cleaner);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
toMap(w, keys, returnTypeMirror, typeArguments.get(0), typeArguments.get(1), maxRows, cal, cleaner);
|
||||
} else if (types.isAssignable(returnTypeMirror, iteratorType)) {
|
||||
final List<? extends TypeMirror> typeArguments = ((DeclaredType) returnTypeMirror).getTypeArguments();
|
||||
if (types.isAssignable(returnTypeMirror, listIteratorType))
|
||||
if (types.isAssignable(returnTypeMirror, resultSetIterableType)) {
|
||||
toResultSetIterable(w, keys, typeArguments.get(0), cal, cleaner, closePs);
|
||||
return false;
|
||||
} else if (types.isAssignable(returnTypeMirror, listIteratorType))
|
||||
toListIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner);
|
||||
else
|
||||
toIterator(w, keys, typeArguments.get(0), maxRows, cal, cleaner);
|
||||
} else {
|
||||
toObject(w, keys, returnTypeMirror, cal, cleaner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public CompileTimeRowToObjectMapper getRowMapper(final String[] keys, TypeMirror returnTypeClass, String cal, TypeMirror mapValType, TypeMirror mapKeyType) {
|
||||
@ -109,6 +121,35 @@ public class CompileTimeResultSetMapper {
|
||||
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 {
|
||||
w.write("\t\t\treturn com.moparisthebest.jdbc.util.ResultSetIterable.getResultSetIterable(rs,\n\t\t\t\t\trs.next() ? ");
|
||||
|
||||
if(java8) {
|
||||
w.append("(rs, ").append(cal == null ? "_cal" : cal).append(") -> {\n");
|
||||
} else {
|
||||
final String returnTypeString = returnTypeMirror.toString();
|
||||
w.append("new com.moparisthebest.jdbc.util.ResultSetToObject<")
|
||||
.append(returnTypeString).append(">() {\n\t\t\t\t\tpublic ")
|
||||
.append(returnTypeString).append(" toObject(final ResultSet rs, final java.util.Calendar ")
|
||||
.append(cal == null ? "_cal" : cal)
|
||||
.append(") throws SQLException {\n");
|
||||
}
|
||||
|
||||
// com.moparisthebest.jdbc.util.ResultSetToObject implementation
|
||||
writeObject(w, keys, returnTypeMirror, cal);
|
||||
w.write("\t\t\t\t\t\treturn ");
|
||||
clean(w, cleaner).write(";\n");
|
||||
// end ResultSetToObject implementation
|
||||
|
||||
if(!java8)
|
||||
w.write("\t\t\t\t\t}\n");
|
||||
|
||||
w.append("\t\t\t\t\t}\n\t\t\t\t: null, ").append(cal == null ? "null" : cal).append(")");
|
||||
if(closePs)
|
||||
w.append(".setPreparedStatementToClose(ps)");
|
||||
w.append(";\n");
|
||||
}
|
||||
|
||||
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 {
|
||||
maxRowInit(w, maxRows).write("\t\t\tfinal ");
|
||||
w.write(returnTypeString);
|
||||
|
@ -349,6 +349,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||
for (final VariableElement param : bindParams)
|
||||
setObject(w, ++count, databaseType, arrayNumberTypeName, arrayStringTypeName, param);
|
||||
|
||||
boolean closeRs = true;
|
||||
if (!parsedSQl.isSelect()) {
|
||||
if (returnType.equals("void")) {
|
||||
w.write("\t\t\tps.executeUpdate();\n");
|
||||
@ -370,20 +371,32 @@ 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;
|
||||
}
|
||||
rsm.mapToResultType(w, keys, eeMethod, maxRows, calendarName, cleanerName);
|
||||
}
|
||||
|
||||
// if no SQLException is thrown, we have to catch it here and wrap it with RuntimeException...
|
||||
if (!sqlExceptionThrown) {
|
||||
w.write("\t\t} catch(SQLException e) {\n\t\t\tthrow new RuntimeException(e);\n");
|
||||
closeRs = rsm.mapToResultType(w, keys, eeMethod, maxRows, calendarName, cleanerName, !cachePreparedStatements);
|
||||
}
|
||||
|
||||
// close things
|
||||
w.write("\t\t} finally {\n");
|
||||
if (parsedSQl.isSelect())
|
||||
w.write("\t\t\ttryClose(rs);\n");
|
||||
if (!cachePreparedStatements)
|
||||
w.write("\t\t\ttryClose(ps);\n");
|
||||
if(closeRs) {
|
||||
// like normal
|
||||
// if no SQLException is thrown, we have to catch it here and wrap it with RuntimeException...
|
||||
if (!sqlExceptionThrown)
|
||||
w.write("\t\t} catch(SQLException e) {\n\t\t\tthrow new RuntimeException(e);\n");
|
||||
w.write("\t\t} finally {\n");
|
||||
if (parsedSQl.isSelect())
|
||||
w.write("\t\t\ttryClose(rs);\n");
|
||||
if (!cachePreparedStatements)
|
||||
w.write("\t\t\ttryClose(ps);\n");
|
||||
} else {
|
||||
// very annoying special handling in that if any exceptions are thrown, we have to close everything even if closeRs == false...
|
||||
w.write("\t\t} catch(Throwable e) {\n");
|
||||
if (parsedSQl.isSelect())
|
||||
w.write("\t\t\ttryClose(rs);\n");
|
||||
if (!cachePreparedStatements)
|
||||
w.write("\t\t\ttryClose(ps);\n");
|
||||
if (sqlExceptionThrown)
|
||||
w.write("\t\t\tif(e instanceof SQLException)\n\t\t\t\tthrow (SQLException)e;\n");
|
||||
w.write("\t\t\tif(e instanceof RuntimeException)\n\t\t\t\tthrow (RuntimeException)e;\n");
|
||||
w.write("\t\t\tthrow new RuntimeException(e);\n");
|
||||
}
|
||||
w.write("\t\t}\n");
|
||||
|
||||
w.write("\t}\n");
|
||||
|
@ -1,12 +1,20 @@
|
||||
package com.moparisthebest.jdbc.codegen;
|
||||
|
||||
import com.moparisthebest.jdbc.dto.FieldPerson;
|
||||
import com.moparisthebest.jdbc.util.ResultSetIterable;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.moparisthebest.jdbc.QueryMapperTest.fieldPerson1;
|
||||
import static com.moparisthebest.jdbc.QueryMapperTest.getConnection;
|
||||
import static com.moparisthebest.jdbc.QueryMapperTest.people;
|
||||
import static com.moparisthebest.jdbc.TryClose.tryClose;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
@ -24,7 +32,7 @@ public class JdbcMapperTest {
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Throwable {
|
||||
//tryClose(dao);
|
||||
tryClose(dao);
|
||||
}
|
||||
|
||||
public PersonDAO getDao() {
|
||||
@ -35,4 +43,30 @@ public class JdbcMapperTest {
|
||||
public void testName() throws Throwable {
|
||||
assertEquals(fieldPerson1.getFirstName(), getDao().getFirstName(fieldPerson1.getPersonNo()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testList() throws SQLException {
|
||||
final List<FieldPerson> fromDb = dao.getPeopleList(people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo());
|
||||
assertArrayEquals(people, fromDb.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultSetIterable() throws SQLException {
|
||||
final ResultSetIterable<FieldPerson> rsi = dao.getPeopleResultSetIterable(people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo());
|
||||
final List<FieldPerson> fromDb = new ArrayList<FieldPerson>();
|
||||
for(final FieldPerson fieldPerson : rsi)
|
||||
fromDb.add(fieldPerson);
|
||||
rsi.close();
|
||||
assertArrayEquals(people, fromDb.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultSetIterableCachedPreparedStatement() throws SQLException {
|
||||
final ResultSetIterable<FieldPerson> rsi = dao.getPeopleResultSetIterableCachedPreparedStatement(people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo());
|
||||
final List<FieldPerson> fromDb = new ArrayList<FieldPerson>();
|
||||
for(final FieldPerson fieldPerson : rsi)
|
||||
fromDb.add(fieldPerson);
|
||||
rsi.close();
|
||||
assertArrayEquals(people, fromDb.toArray());
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package com.moparisthebest.jdbc.codegen;
|
||||
import com.moparisthebest.jdbc.Cleaner;
|
||||
import com.moparisthebest.jdbc.dto.FieldPerson;
|
||||
import com.moparisthebest.jdbc.dto.Person;
|
||||
import com.moparisthebest.jdbc.util.ResultSetIterable;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
@ -15,10 +17,10 @@ import java.util.*;
|
||||
@JdbcMapper.Mapper(
|
||||
// jndiName = "bob",
|
||||
// databaseType = JdbcMapper.DatabaseType.ORACLE
|
||||
// cachePreparedStatements = false
|
||||
cachePreparedStatements = JdbcMapper.OptionalBool.FALSE
|
||||
// , sqlParser = SimpleSQLParser.class
|
||||
)
|
||||
public interface PersonDAO {
|
||||
public interface PersonDAO extends Closeable {
|
||||
|
||||
@JdbcMapper.SQL("UPDATE person SET first_name = {firstName} WHERE last_name = {lastName}")
|
||||
int setFirstName(String firstName, String lastName);
|
||||
@ -132,4 +134,14 @@ public interface PersonDAO {
|
||||
Map<String, FieldPerson> getPersonStaticLimitMap(long personNo) throws SQLException;
|
||||
@JdbcMapper.SQL(value = "SELECT first_name, last_name, birth_date FROM person WHERE person_no = {personNo}", maxRows = Long.MAX_VALUE)
|
||||
Map<String, List<FieldPerson>> getPersonStaticLimitMapList(long personNo) throws SQLException;
|
||||
|
||||
|
||||
@JdbcMapper.SQL("SELECT person_no, birth_date, last_name, first_name from person WHERE person_no IN ({personNo1},{personNo2},{personNo3}) ORDER BY person_no")
|
||||
List<FieldPerson> getPeopleList(long personNo1, long personNo2, long personNo3) throws SQLException;
|
||||
|
||||
@JdbcMapper.SQL("SELECT person_no, birth_date, last_name, first_name from person WHERE person_no IN ({personNo1},{personNo2},{personNo3}) ORDER BY person_no")
|
||||
ResultSetIterable<FieldPerson> getPeopleResultSetIterable(long personNo1, long personNo2, long personNo3) throws SQLException;
|
||||
|
||||
@JdbcMapper.SQL(value = "SELECT person_no, birth_date, last_name, first_name from person WHERE person_no IN ({personNo1},{personNo2},{personNo3}) ORDER BY person_no", cachePreparedStatement = JdbcMapper.OptionalBool.TRUE)
|
||||
ResultSetIterable<FieldPerson> getPeopleResultSetIterableCachedPreparedStatement(long personNo1, long personNo2, long personNo3) throws SQLException;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user