Scala+SlickでTupple22問題を解決してみた

slickというかscalaには有名なタプル22問題があります。

23項目以上のメンバを持ったcase classが作れない。

どうやらscala2.11では解消されているようですが、まだベータ版ということで使うのにはためらいます

そこでネストしたcase classを用いて23カラム以上持つデータベースのテーブルを取得するものを作成してみました

  • scala2.10.2
  • slick2.10-1.0.1
  • eclipse 4.3
  • Tests.scala

import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession
import scala.slick.jdbc.{GetResult, StaticQuery => Q}
import Q.interpolation

	 case class PartA(a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07:Int, a08:Int, a09:Int, a10:Int)
	 case class PartB(a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17:Int, a18:Int, a19:Int, a20:Int)
	 case class PartC(a21: Int, a22: Int, a23: Int, a24: Int)
	 case class Whole(id: Int, p1: PartA, p2: PartB, p3: PartC)

		object Tests extends Table[Int]("test"){
			def id = column[Int]("id", O.PrimaryKey)
			def a01 = column[Int]("a01")
			def a02 = column[Int]("a02")
			def a03 = column[Int]("a03")
			def a04 = column[Int]("a04")
			def a05 = column[Int]("a05")
			def a06 = column[Int]("a06")
			def a07 = column[Int]("a07")
			def a08 = column[Int]("a08")
			def a09 = column[Int]("a09")
			def a10 = column[Int]("a10")
			def a11 = column[Int]("a11")
			def a12 = column[Int]("a12")
			def a13 = column[Int]("a13")
			def a14 = column[Int]("a14")
			def a15 = column[Int]("a15")
			def a16 = column[Int]("a16")
			def a17 = column[Int]("a17")
			def a18 = column[Int]("a18")
			def a19 = column[Int]("a19")
			def a20 = column[Int]("a20")
			def a21 = column[Int]("a21")
			def a22 = column[Int]("a22")
			def a23 = column[Int]("a23")
			def a24 = column[Int]("a24")

			def * = id

			def all = (
				id,
				(a01, a02, a03, a04, a05, a06, a07, a08, a09, a10),
				(a11, a12, a13, a14, a15, a16, a17, a18, a19, a20),
				(a21, a22, a23, a24)
			)
	
			private def connectDB[Any](db:javax.sql.DataSource,f: => Any): Any = {
				Database.forDataSource(db) withSession {f}
			} 
			implicit val sqlToClass=GetResult(rs=>Whole(rs<<,PartA(rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<),PartB(rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<),PartC(rs<<,rs<<,rs<<,rs<<)))
 
			def select(db:javax.sql.DataSource,id:String):Option[Whole]= {
				connectDB(db,
				{
				sql"select 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4 ".as[Whole].list.headOption
				}
		)
	}
}

  • TestsTest.scala

import javax.sql._
import javax.naming._

import org.junit._

import com.mysql.jdbc.jdbc2.optional._

class StockMasterTest {
	 private def testDataSource:javax.sql.DataSource={
	System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory")
	System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming")
	val ic = new InitialContext()
	ic.createSubcontext("java:")
	ic.createSubcontext("java:comp")
	ic.createSubcontext("java:comp/env")
	ic.createSubcontext("java:comp/env/jdbc")

		val ds = new MysqlConnectionPoolDataSource()
	ds.setUser("root")
	ds.setPassword("password")
	ds.setDatabaseName("dbname")
	ds.setServerName("localhost")
	ds.setPortNumber(3306)
	ic.bind("java:comp/env/jdbc/database", ds)
	ds
	} 

	@Test
	def select:Unit={
		val list=Tests.select(testDataSource,"id");
		println(list)

	}

}
  • eclipse4.3で実行
Some(Whole(0,PartA(1,2,3,4,5,6,7,8,9,0),PartB(1,2,3,4,5,6,7,8,9,0),PartC(1,2,3,4)))

とりあえず動いているようです