Add @JdbcMapper.RunInTransaction and static support methods to QueryRunner
This commit is contained in:
parent
3675ae0f73
commit
72906cf3c5
|
@ -2,6 +2,7 @@ package com.moparisthebest.jdbc;
|
||||||
|
|
||||||
import com.moparisthebest.jdbc.codegen.JdbcMapper;
|
import com.moparisthebest.jdbc.codegen.JdbcMapper;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
@ -97,31 +98,103 @@ public class QueryRunner<T extends JdbcMapper> {
|
||||||
T dao = null;
|
T dao = null;
|
||||||
try {
|
try {
|
||||||
dao = factory.create();
|
dao = factory.create();
|
||||||
dao.getConnection().setAutoCommit(false);
|
return runInTransaction(dao, query);
|
||||||
final E ret = query.run(dao);
|
} finally {
|
||||||
dao.getConnection().commit();
|
if (dao != null)
|
||||||
return ret;
|
tryClose(dao);
|
||||||
} catch (final Throwable e) {
|
}
|
||||||
if (dao != null) {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For running existing JdbcMapper in transaction
|
||||||
|
* @param dao
|
||||||
|
* @param query
|
||||||
|
* @param <T>
|
||||||
|
* @param <E>
|
||||||
|
* @return
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public static <T extends JdbcMapper, E> E runInTransaction(final T dao, final Runner<T, E> query) throws SQLException {
|
||||||
|
if (query == null)
|
||||||
|
throw new NullPointerException("query must be non-null");
|
||||||
|
if (dao == null)
|
||||||
|
throw new NullPointerException("dao must be non-null");
|
||||||
|
if(!dao.getConnection().getAutoCommit()) {
|
||||||
|
// if we are already in a transaction, the calling code will do the right thing
|
||||||
|
// we don't want to change autoCommit, commit, or rollback
|
||||||
|
return query.run(dao);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
dao.getConnection().setAutoCommit(false);
|
||||||
|
final E ret = query.run(dao);
|
||||||
|
dao.getConnection().commit();
|
||||||
|
return ret;
|
||||||
|
} catch (final Throwable e) {
|
||||||
try {
|
try {
|
||||||
dao.getConnection().rollback();
|
dao.getConnection().rollback();
|
||||||
} catch (SQLException excep) {
|
} catch (SQLException excep) {
|
||||||
// ignore to throw original
|
// ignore to throw original
|
||||||
}
|
}
|
||||||
}
|
if (e instanceof SQLException)
|
||||||
if (e instanceof SQLException)
|
throw (SQLException) e;
|
||||||
throw (SQLException) e;
|
if (e instanceof RuntimeException)
|
||||||
if (e instanceof RuntimeException)
|
throw (RuntimeException) e;
|
||||||
throw (RuntimeException) e;
|
throw new RuntimeException("odd error should never happen", e);
|
||||||
throw new RuntimeException("odd error should never happen", e);
|
} finally {
|
||||||
} finally {
|
|
||||||
if (dao != null) {
|
|
||||||
try {
|
try {
|
||||||
dao.getConnection().setAutoCommit(true);
|
dao.getConnection().setAutoCommit(true);
|
||||||
} catch (SQLException excep) {
|
} catch (SQLException excep) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
tryClose(dao);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For running against an existing raw connection for things not implementing JdbcMapper
|
||||||
|
*
|
||||||
|
* this could construct a JdbcMapper instance with the Connection and re-use the method above,
|
||||||
|
* with a bit of a performance/allocation hit, we'll skip for now
|
||||||
|
*
|
||||||
|
* @param dao
|
||||||
|
* @param query
|
||||||
|
* @param <T>
|
||||||
|
* @param <E>
|
||||||
|
* @return
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public static <T extends Connection, E> E runConnectionInTransaction(final T dao, final Runner<T, E> query) throws SQLException {
|
||||||
|
if (query == null)
|
||||||
|
throw new NullPointerException("query must be non-null");
|
||||||
|
if (dao == null)
|
||||||
|
throw new NullPointerException("dao must be non-null");
|
||||||
|
if(!dao.getAutoCommit()) {
|
||||||
|
// if we are already in a transaction, the calling code will do the right thing
|
||||||
|
// we don't want to change autoCommit, commit, or rollback
|
||||||
|
return query.run(dao);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
dao.setAutoCommit(false);
|
||||||
|
final E ret = query.run(dao);
|
||||||
|
dao.commit();
|
||||||
|
return ret;
|
||||||
|
} catch (final Throwable e) {
|
||||||
|
try {
|
||||||
|
dao.rollback();
|
||||||
|
} catch (SQLException excep) {
|
||||||
|
// ignore to throw original
|
||||||
|
}
|
||||||
|
if (e instanceof SQLException)
|
||||||
|
throw (SQLException) e;
|
||||||
|
if (e instanceof RuntimeException)
|
||||||
|
throw (RuntimeException) e;
|
||||||
|
throw new RuntimeException("odd error should never happen", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
dao.setAutoCommit(true);
|
||||||
|
} catch (SQLException excep) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,13 @@ public interface JdbcMapper extends Closeable {
|
||||||
*/
|
*/
|
||||||
public @interface WarnOnUnusedParams {}
|
public @interface WarnOnUnusedParams {}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
/**
|
||||||
|
* Run this method in a transaction, useless on @SQL methods because they only run single statements, helpful on default or abstract methods that chain calls
|
||||||
|
*/
|
||||||
|
public @interface RunInTransaction {}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@Target({ElementType.METHOD})
|
@Target({ElementType.METHOD})
|
||||||
public @interface SQL {
|
public @interface SQL {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
//IFJAVA8_END
|
//IFJAVA8_END
|
||||||
|
|
||||||
|
import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.java8;
|
||||||
import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorStringNoGenerics;
|
import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorStringNoGenerics;
|
||||||
import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorToClass;
|
import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorToClass;
|
||||||
|
|
||||||
|
@ -33,32 +34,16 @@ import static com.moparisthebest.jdbc.codegen.JdbcMapperProcessor.typeMirrorToCl
|
||||||
*/
|
*/
|
||||||
public class CompileTimeResultSetMapper {
|
public class CompileTimeResultSetMapper {
|
||||||
|
|
||||||
public static final SourceVersion RELEASE_8;
|
|
||||||
|
|
||||||
static {
|
|
||||||
SourceVersion rl8 = null;
|
|
||||||
try {
|
|
||||||
rl8 = SourceVersion.valueOf("RELEASE_8");
|
|
||||||
} catch(Throwable e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
RELEASE_8 = rl8;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Types types;
|
public final Types types;
|
||||||
public final TypeMirror collectionType, mapType, mapCollectionType, iteratorType, listIteratorType, finishableType, resultSetType, resultSetIterableType, byteArrayType;
|
public final TypeMirror collectionType, mapType, mapCollectionType, iteratorType, listIteratorType, finishableType, resultSetType, resultSetIterableType, byteArrayType;
|
||||||
//IFJAVA8_START
|
//IFJAVA8_START
|
||||||
public final TypeMirror streamType;
|
public final TypeMirror streamType;
|
||||||
//IFJAVA8_END
|
//IFJAVA8_END
|
||||||
private final boolean java8;
|
|
||||||
|
|
||||||
public CompileTimeResultSetMapper(final ProcessingEnvironment processingEnv) {
|
public CompileTimeResultSetMapper(final ProcessingEnvironment processingEnv) {
|
||||||
types = processingEnv.getTypeUtils();
|
types = processingEnv.getTypeUtils();
|
||||||
final Elements elements = processingEnv.getElementUtils();
|
final Elements elements = processingEnv.getElementUtils();
|
||||||
|
|
||||||
// is this the proper way to do this?
|
|
||||||
java8 = RELEASE_8 != null && processingEnv.getSourceVersion().ordinal() >= RELEASE_8.ordinal();
|
|
||||||
|
|
||||||
collectionType = types.getDeclaredType(elements.getTypeElement(Collection.class.getCanonicalName()), types.getWildcardType(null, null));
|
collectionType = types.getDeclaredType(elements.getTypeElement(Collection.class.getCanonicalName()), types.getWildcardType(null, null));
|
||||||
mapType = types.getDeclaredType(elements.getTypeElement(Map.class.getCanonicalName()), types.getWildcardType(null, null), types.getWildcardType(null, null));
|
mapType = types.getDeclaredType(elements.getTypeElement(Map.class.getCanonicalName()), types.getWildcardType(null, null), types.getWildcardType(null, null));
|
||||||
mapCollectionType = types.getDeclaredType(elements.getTypeElement(Map.class.getCanonicalName()), types.getWildcardType(null, null), types.getWildcardType(collectionType, null));
|
mapCollectionType = types.getDeclaredType(elements.getTypeElement(Map.class.getCanonicalName()), types.getWildcardType(null, null), types.getWildcardType(collectionType, null));
|
||||||
|
|
|
@ -33,6 +33,19 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
private static final Pattern paramPattern = Pattern.compile("\\{(([^\\s]+)\\s+(([Nn][Oo][Tt]\\s+)?[Ii][Nn]\\s+))?([^}]+)\\}");
|
private static final Pattern paramPattern = Pattern.compile("\\{(([^\\s]+)\\s+(([Nn][Oo][Tt]\\s+)?[Ii][Nn]\\s+))?([^}]+)\\}");
|
||||||
|
|
||||||
|
public static final SourceVersion RELEASE_8;
|
||||||
|
public static boolean java8;
|
||||||
|
|
||||||
|
static {
|
||||||
|
SourceVersion rl8 = null;
|
||||||
|
try {
|
||||||
|
rl8 = SourceVersion.valueOf("RELEASE_8");
|
||||||
|
} catch(Throwable e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
RELEASE_8 = rl8;
|
||||||
|
}
|
||||||
|
|
||||||
private static Types types;
|
private static Types types;
|
||||||
private static Messager messager;
|
private static Messager messager;
|
||||||
|
|
||||||
|
@ -44,7 +57,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||||
return messager;
|
return messager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType,
|
private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType, jdbcMapperType,
|
||||||
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType, calendarType, cleanerType;
|
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType, calendarType, cleanerType;
|
||||||
//IFJAVA8_START
|
//IFJAVA8_START
|
||||||
private TypeMirror instantType, localDateTimeType, localDateType, localTimeType, zonedDateTimeType, offsetDateTimeType, offsetTimeType;
|
private TypeMirror instantType, localDateTimeType, localDateType, localTimeType, zonedDateTimeType, offsetDateTimeType, offsetTimeType;
|
||||||
|
@ -62,6 +75,10 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(final ProcessingEnvironment processingEnv) {
|
public synchronized void init(final ProcessingEnvironment processingEnv) {
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
|
|
||||||
|
// is this the proper way to do this?
|
||||||
|
java8 = RELEASE_8 != null && processingEnv.getSourceVersion().ordinal() >= RELEASE_8.ordinal();
|
||||||
|
|
||||||
types = processingEnv.getTypeUtils();
|
types = processingEnv.getTypeUtils();
|
||||||
messager = processingEnv.getMessager();
|
messager = processingEnv.getMessager();
|
||||||
final Elements elements = processingEnv.getElementUtils();
|
final Elements elements = processingEnv.getElementUtils();
|
||||||
|
@ -71,6 +88,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();
|
||||||
|
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();
|
||||||
blobType = elements.getTypeElement(Blob.class.getCanonicalName()).asType();
|
blobType = elements.getTypeElement(Blob.class.getCanonicalName()).asType();
|
||||||
|
@ -209,8 +227,14 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
for (final Element methodElement : genClass.getEnclosedElements()) {
|
for (final Element methodElement : genClass.getEnclosedElements()) {
|
||||||
// can only implement abstract methods
|
// can only implement abstract methods
|
||||||
if (methodElement.getKind() != ElementKind.METHOD || !methodElement.getModifiers().contains(Modifier.ABSTRACT))
|
if (methodElement.getKind() != ElementKind.METHOD) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
if (!methodElement.getModifiers().contains(Modifier.ABSTRACT)) {
|
||||||
|
if (methodElement.getAnnotation(JdbcMapper.RunInTransaction.class) != null)
|
||||||
|
outputRunInTransaction((ExecutableElement) methodElement, w);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final ExecutableElement eeMethod = (ExecutableElement) methodElement;
|
final ExecutableElement eeMethod = (ExecutableElement) methodElement;
|
||||||
if (lookupCloseMethod)
|
if (lookupCloseMethod)
|
||||||
if ((closeMethod = getCloseMethod(eeMethod)) != null) {
|
if ((closeMethod = getCloseMethod(eeMethod)) != null) {
|
||||||
|
@ -223,6 +247,10 @@ 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);
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL with non-empty query is required on abstract or interface methods", methodElement);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (eeMethod.getAnnotation(JdbcMapper.RunInTransaction.class) != null) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL is incompatible with @JdbcMapper.RunInTransaction", methodElement);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final boolean allowReflection = sql.allowReflection().combine(defaultAllowReflection);
|
final boolean allowReflection = sql.allowReflection().combine(defaultAllowReflection);
|
||||||
w.write("\n\t@Override\n\tpublic ");
|
w.write("\n\t@Override\n\tpublic ");
|
||||||
final String returnType = eeMethod.getReturnType().toString();
|
final String returnType = eeMethod.getReturnType().toString();
|
||||||
|
@ -481,6 +509,97 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void outputRunInTransaction(final ExecutableElement eeMethod, final Writer w) throws IOException {
|
||||||
|
w.write("\n\t@Override\n\tpublic ");
|
||||||
|
final String returnType = eeMethod.getReturnType().toString();
|
||||||
|
w.write(returnType);
|
||||||
|
w.write(" ");
|
||||||
|
w.write(eeMethod.getSimpleName().toString());
|
||||||
|
w.write('(');
|
||||||
|
|
||||||
|
boolean sqlExceptionThrown = false;
|
||||||
|
final List<? extends VariableElement> params = eeMethod.getParameters();
|
||||||
|
final int numParams = params.size();
|
||||||
|
{
|
||||||
|
// now parameters
|
||||||
|
int count = 0;
|
||||||
|
for (final VariableElement param : params) {
|
||||||
|
writeAllParamAnnotations(w, param);
|
||||||
|
w.write("final ");
|
||||||
|
w.write(param.asType().toString());
|
||||||
|
w.write(' ');
|
||||||
|
final String name = param.getSimpleName().toString();
|
||||||
|
w.write(name);
|
||||||
|
if (++count != numParams)
|
||||||
|
w.write(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// throws?
|
||||||
|
w.write(")");
|
||||||
|
final List<? extends TypeMirror> thrownTypes = eeMethod.getThrownTypes();
|
||||||
|
final int numThrownTypes = thrownTypes.size();
|
||||||
|
if (numThrownTypes > 0) {
|
||||||
|
count = 0;
|
||||||
|
w.write(" throws ");
|
||||||
|
}
|
||||||
|
for (final TypeMirror thrownType : thrownTypes) {
|
||||||
|
sqlExceptionThrown |= types.isSameType(thrownType, sqlExceptionType);
|
||||||
|
w.write(thrownType.toString());
|
||||||
|
if (++count != numThrownTypes)
|
||||||
|
w.write(", ");
|
||||||
|
}
|
||||||
|
w.write(" {\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Element thisDao = eeMethod.getEnclosingElement();
|
||||||
|
final boolean thisDaoImplementsJdbcMapper = types.isAssignable(thisDao.asType(), jdbcMapperType);
|
||||||
|
final String thisDaoName = thisDao.getSimpleName().toString();
|
||||||
|
|
||||||
|
if(!java8)
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.RunInTransaction cannot be used in java6 yet, java8+ only", eeMethod);
|
||||||
|
|
||||||
|
// todo: *can* this be done in java6 without reflection or something? we need to call super, not this, which causes infinite recursion, bail for now
|
||||||
|
if(!java8)
|
||||||
|
w.append("\t\tfinal ").append(thisDaoName).append(" jdbcMapperGeneratedTransactionThis = this;\n");
|
||||||
|
|
||||||
|
w.write("\t\treturn com.moparisthebest.jdbc.QueryRunner.run");
|
||||||
|
if(thisDaoImplementsJdbcMapper)
|
||||||
|
w.write("InTransaction(this, ");
|
||||||
|
else
|
||||||
|
w.write("ConnectionInTransaction(this.conn, ");
|
||||||
|
|
||||||
|
if(!java8) {
|
||||||
|
w.append("new com.moparisthebest.jdbc.QueryRunner.Runner<").append(thisDaoName).append(", ").append(returnType).append(">() {\n" +
|
||||||
|
"\t\t\t@Override\n" +
|
||||||
|
"\t\t\tpublic ").append(returnType).append(" run(").append(eeMethod.getEnclosingElement().getSimpleName()).append(" dao) throws SQLException {\n" +
|
||||||
|
"\t\t\t\treturn jdbcMapperGeneratedTransactionThis");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
w.append("dao -> ");
|
||||||
|
//IFJAVA8_START
|
||||||
|
if (eeMethod.getModifiers().contains(Modifier.DEFAULT))
|
||||||
|
w.append(thisDaoName).append(".");
|
||||||
|
//IFJAVA8_END
|
||||||
|
w.append("super");
|
||||||
|
}
|
||||||
|
w.append(".").append(eeMethod.getSimpleName().toString()).append('(');
|
||||||
|
int count = 0;
|
||||||
|
for (final VariableElement param : params) {
|
||||||
|
final String name = param.getSimpleName().toString();
|
||||||
|
w.write(name);
|
||||||
|
if (++count != numParams)
|
||||||
|
w.write(", ");
|
||||||
|
}
|
||||||
|
w.append(')');
|
||||||
|
|
||||||
|
if(!java8)
|
||||||
|
w.append(";\n\t\t\t}\n" +
|
||||||
|
"\t\t}");
|
||||||
|
|
||||||
|
w.write(");\n");
|
||||||
|
w.write("\t}\n");
|
||||||
|
}
|
||||||
|
|
||||||
private void setObject(final Writer w, final int index, final JdbcMapper.DatabaseType databaseType, final String arrayNumberTypeName, final String arrayStringTypeName, final VariableElement param) throws SQLException, IOException {
|
private void setObject(final Writer w, final int index, final JdbcMapper.DatabaseType databaseType, final String arrayNumberTypeName, final String arrayStringTypeName, final VariableElement param) throws SQLException, IOException {
|
||||||
String variableName = param.getSimpleName().toString();
|
String variableName = param.getSimpleName().toString();
|
||||||
final TypeMirror o = param.asType();
|
final TypeMirror o = param.asType();
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.moparisthebest.jdbc.codegen;
|
||||||
|
|
||||||
|
import com.moparisthebest.jdbc.dto.FieldPerson;
|
||||||
|
import com.moparisthebest.jdbc.dto.Person;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
@JdbcMapper.Mapper(
|
||||||
|
// databaseType = JdbcMapper.DatabaseType.ORACLE
|
||||||
|
cachePreparedStatements = JdbcMapper.OptionalBool.FALSE
|
||||||
|
// , sqlParser = SimpleSQLParser.class
|
||||||
|
, allowReflection = JdbcMapper.OptionalBool.TRUE
|
||||||
|
)
|
||||||
|
public abstract class AbstractDao {
|
||||||
|
|
||||||
|
@JdbcMapper.SQL(value = "SELECT person_no, first_name, last_name, birth_date FROM person WHERE person_no = {personNo}")
|
||||||
|
abstract FieldPerson getPerson(long personNo) throws SQLException;
|
||||||
|
|
||||||
|
@JdbcMapper.SQL("SELECT person_no FROM person WHERE last_name = {lastName}")
|
||||||
|
abstract long getPersonNo(String lastName) throws SQLException;
|
||||||
|
|
||||||
|
//IFJAVA8_START
|
||||||
|
@JdbcMapper.RunInTransaction
|
||||||
|
//IFJAVA8_END
|
||||||
|
protected Person getPersonInTransaction(final String lastName) throws SQLException {
|
||||||
|
return getPerson(getPersonNo(lastName));
|
||||||
|
}
|
||||||
|
}
|
|
@ -237,6 +237,11 @@ public interface PersonDAO extends JdbcMapper {
|
||||||
@JdbcMapper.SQL("SELECT str_val FROM val WHERE val_no = {valNo}")
|
@JdbcMapper.SQL("SELECT str_val FROM val WHERE val_no = {valNo}")
|
||||||
ZoneOffset getZoneOffsetStr(long valNo);
|
ZoneOffset getZoneOffsetStr(long valNo);
|
||||||
|
|
||||||
|
@JdbcMapper.RunInTransaction
|
||||||
|
default Person getPersonInTransaction(final String lastName) throws SQLException {
|
||||||
|
return getPerson(getPersonNo(lastName));
|
||||||
|
}
|
||||||
|
|
||||||
//IFJAVA8_END
|
//IFJAVA8_END
|
||||||
|
|
||||||
// test blob
|
// test blob
|
||||||
|
|
Loading…
Reference in New Issue