Skip to content

Instantly share code, notes, and snippets.

@thomasnield
Last active June 3, 2017 00:31
Show Gist options
  • Select an option

  • Save thomasnield/9c391a588af04c49747d3a2224db285c to your computer and use it in GitHub Desktop.

Select an option

Save thomasnield/9c391a588af04c49747d3a2224db285c to your computer and use it in GitHub Desktop.
JDBC ResultSet to Data Class
// Bring in Google Guava as a dependency
// compile 'com.google.guava:guava:22.0'
import com.google.common.base.CaseFormat
import java.sql.ResultSet
fun ResultSet.toDataClass(): String {
val table = metaData.getTableName(1).let { it.substring(0,1) + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, it.substring(1)) }
val headers = (1..metaData.columnCount).asSequence()
.map { metaData.getColumnName(it) }
.toList()
val types = (1..metaData.columnCount).asSequence()
.map {
it to when {
metaData.getColumnClassName(it).contains(".Integer") -> "Int"
metaData.getColumnClassName(it).contains(".String") -> "String"
metaData.getColumnClassName(it).contains(".Date") -> "LocalDate"
metaData.getColumnClassName(it).contains(".Timestamp") -> "LocalDateTime"
metaData.getColumnClassName(it).contains(".BigDecimal") -> "BigDecimal"
metaData.getColumnClassName(it).contains(".Long") -> "Long"
else -> "String"
}
}.map { if (metaData.isNullable(it.first) == 1) "${it.second}?" else it.second }
.toList()
fun buildField(index: Int) = " val ${CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, headers[index])}: ${types[index]}"
val parameters = headers.map { CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, it) }
val tableFields = (0..(headers.size - 1)).asSequence().map { buildField(it) }.joinToString(",\n")
data class TypeHeaderParameter(val type: String, val header: String, val parameter: String)
val resultSetConstructor = types.asSequence().zip(headers.asSequence()).zip(parameters.asSequence())
.map { TypeHeaderParameter(it.first.first, it.first.second, it.second) }
.map { thp ->
val header = "\"${thp.header}\""
val parameter = "${thp.parameter} ="
when(thp.type.replace("?","")) {
"Int" -> "$parameter rs.getInt($header)"
"String" -> "$parameter rs.getString($header)"
"LocalDate" -> "$parameter rs.getLocalDate($header)"
"LocalDateTime" -> "$parameter rs.getLocalDateTime($header)"
"BigDecimal" -> "$parameter rs.getBigDecimal($header)"
"Long" -> "$parameter rs.getLong($header)"
else -> throw Exception("Unmapped type!")
}
}.joinToString(",\n ").let { "constructor(rs: ResultSet): this(\n $it\n)"}
return "data class $table (\n$tableFields\n) {\n $resultSetConstructor \n}"
}
fun ResultSet.getLocalDate(colName: String) = this.getDate(colName)?.toLocalDate()
fun ResultSet.getLocalDate(colIndex: Int) = this.getDate(colIndex)?.toLocalDate()
fun ResultSet.getLocalDateTime(colName: String) = this.getTimestamp(colName)?.toLocalDateTime()
fun ResultSet.getLocalDateTime(colIndex: Int) = this.getTimestamp(colIndex)?.toLocalDateTime()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment