Created
September 28, 2015 01:45
-
-
Save newjam/650a6313ac7619571e55 to your computer and use it in GitHub Desktop.
Get free jdbi ResultSetMapper if your class has a constructor from a ResultSet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Constructor; | |
import java.lang.reflect.InvocationTargetException; | |
import java.sql.ResultSet; | |
import java.sql.SQLException; | |
import java.util.Optional; | |
import lombok.extern.slf4j.Slf4j; | |
import org.skife.jdbi.v2.ResultSetMapperFactory; | |
import org.skife.jdbi.v2.StatementContext; | |
import org.skife.jdbi.v2.tweak.ResultSetMapper; | |
/** | |
* Automatically create a ResultSetMapper if the type has a constructor that accepts a ResultSet | |
*/ | |
@Slf4j | |
public class ConstructorResultSetMapperFactory implements ResultSetMapperFactory { | |
private static Optional<Constructor<?>> getConstructor(Class type) { | |
try { | |
return Optional.of(type.getConstructor(ResultSet.class)); | |
} catch (NoSuchMethodException | SecurityException ex) { | |
return Optional.empty(); | |
} | |
} | |
private static class ConstructorResultSetMapper implements ResultSetMapper { | |
private final Constructor constructor; | |
public ConstructorResultSetMapper(Constructor constructor) { | |
this.constructor = constructor; | |
} | |
@Override | |
public Object map(int i, ResultSet rs, StatementContext sc) throws SQLException { | |
try { | |
return constructor.newInstance(rs); | |
} catch(InvocationTargetException ex) { | |
Throwable cause = ex.getCause(); | |
// Don't mangle useful exceptions! | |
if(cause != null && cause instanceof SQLException) { | |
throw (SQLException) cause; | |
} else { | |
throw new RuntimeException(ex); | |
} | |
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException ex) { | |
throw new RuntimeException(ex); | |
} | |
} | |
} | |
@Override | |
public boolean accepts(Class type, StatementContext sc) { | |
return getConstructor(type).isPresent(); | |
} | |
private static ResultSetMapper fromConstructor(Constructor constructor) { | |
log.debug("Automatically creating ResultSetMapper<{}> from constructor.", constructor.getDeclaringClass().getSimpleName()); | |
return new ConstructorResultSetMapper(constructor); | |
} | |
@Override | |
public ResultSetMapper mapperFor(Class type, StatementContext sc) { | |
return getConstructor(type) | |
.map(ConstructorResultSetMapperFactory::fromConstructor) | |
.orElseThrow(RuntimeException::new); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment