Proof of concept of a ResultSet to case class mapper in scala
import java.sql.ResultSet
object ResultSetReaders {
trait Reader[T] {
def fromResultSet(column: Int, rs: ResultSet): T
}
implicit val stringReader = new Reader[String] {
override def fromResultSet(column: Int, rs: ResultSet): String = {
rs.getString(column)
}
}
implicit val intReader = new Reader[Int] {
override def fromResultSet(column: Int, rs: ResultSet): Int = {
rs.getInt(column)
}
}
}
import ResultSetReaders._
object Mapper {
def apply[T, V, R](constructor: (T, V) => R)(implicit evT: Reader[T], evV: Reader[V]): ResultSet => R = {
(rs: ResultSet) => {
constructor(
evT.fromResultSet(1, rs),
evV.fromResultSet(2, rs)
)
}
}
def apply[T, V, W, R](constructor: (T, V, W) => R)(implicit evT: Reader[T], evV: Reader[V], evW: Reader[W]): ResultSet => R = {
(rs: ResultSet) => {
constructor(
evT.fromResultSet(1, rs),
evV.fromResultSet(2, rs),
evW.fromResultSet(3, rs)
)
}
}
}
object SequenceMapper {
def apply[T, V, R](constructor: (T, V) => R)(implicit evT: Reader[T], evV: Reader[V]): ResultSet => Seq[R] = {
buildSequenceMapper(Mapper(constructor))
}
def apply[T, V, W, R](constructor: (T, V, W) => R)(implicit evT: Reader[T], evV: Reader[V], evW: Reader[W]): ResultSet => Seq[R] = {
buildSequenceMapper(Mapper(constructor))
}
private def buildSequenceMapper[T,R](mapper:ResultSet => R): (ResultSet) => Seq[R] = {
(rs:ResultSet) => {
val result = scala.collection.mutable.ListBuffer.empty[R]
while (rs.next()) {
result.append(mapper(rs))
}
result
}
}
}
val rs = new org.h2.tools.SimpleResultSet()
rs.addColumn("name", java.sql.Types.VARCHAR, 80, 0)
rs.addColumn("points", java.sql.Types.INTEGER, 80, 0)
rs.addRow("Jose", new Integer(4))
case class Score(name: String, points: Int)
val personMapper: (ResultSet) => Seq[Score] = SequenceMapper(Score.apply _)
val s = personMapper(rs).head
val rs3 = new org.h2.tools.SimpleResultSet()
rs3.addColumn("name", java.sql.Types.VARCHAR, 80, 0)
rs3.addColumn("points", java.sql.Types.INTEGER, 80, 0)
rs3.addColumn("ranking", java.sql.Types.INTEGER, 80, 0)
rs3.addRow("Jose", new Integer(4), new Integer(2))
case class ScoreWithRanking(name: String, points: Int,ranking: Int)
val rankingMapper: (ResultSet) => Seq[ScoreWithRanking] = SequenceMapper(ScoreWithRanking.apply _)
rankingMapper(rs3).head