JDBCドライバをScalaのIteratorで皮を被せた実装です。
これは、Seedoフレームワークの中心的な部分です。
Javaで実装したSeedoフレームワークでは、Iterator部分が別Classとなる実装でしたが、Scalaではすっきりと1つのClassの中に記述できてしまいます。
内容はJDBCドライバの関数を生で記述したことがある人であればすぐに理解できるものです。
最近は、JDBCドライバの関数で直接コードを書く機会がないと思いますが、お使いのフレームワークの中身とこれとは似たようなものでしょう。
prepareStatement関数を使ったgetObjectによってレコードカラムのデータを取得するコーディングです。
def executeQueryIterator = new Iterator[Array[Any]] { if(sqlMarker != rdbms._SELECT_){ throw new Exception("SQL sentence should be SELECT phrase") } var pstmt:PreparedStatement = con.prepareStatement(getSql) var parameterIndex = 1 if (parameters != null) { for (i <- 0 to parameters.length - 1) { pstmt.setObject(parameterIndex, parameters(i)) parameterIndex += 1 } } var rs:ResultSet = pstmt.executeQuery var orsmd:ResultSetMetaData = rs.getMetaData var numColumns = orsmd.getColumnCount columnNameList = new Array[String](numColumns) // make array for column name for (i <- 1 to numColumns) { // get column name columnNameList(i-1) = orsmd.getColumnName (i) } override def hasNext : Boolean = { try { val r = rs.next // read next record if(!r) close return r } catch { case e:SQLException => { e.printStackTrace } } return false } override def next : Array[Any] = { val rec = new Array[Any](numColumns) // make array for one record var i = 0 for (j <- 1 to numColumns) { val tp = orsmd.getColumnType (j) try { rec(i) = rs.getObject(j) } catch { case e:SQLException => { errorMessage = "Warning "+e.getMessage System.err.println(errorMessage) close } } i += 1 } rec } def close :Unit = { try { if (pstmt != null) { pstmt.close pstmt = null } if (rs != null){ rs.close rs = null } } catch { case e:SQLException => { e.printStackTrace } } } clear }
override def hasNext では、rs.next を呼び出しています。
rs.hasNext や rs.isLast や rs.last が使えるといいのですが、
Oracleデータベースでは、prepareStatement関数が、TYPE_SCROLL_INSENSITIVEでないResultSetを作るため例外を発してしまいます。PostgreSQLのJDBCドライバでは問題はないようです。
次のscalatestによるテストコードは、Seedoフレームワークのテスト用のものです。
import org.scalatest.junit.{JUnitSuite,ShouldMatchersForJUnit} import org.junit.{Test,Before,After,BeforeClass,AfterClass} import seedo._ import seedo.database._ import scott.bean._ class testDB extends JUnitSuite with ShouldMatchersForJUnit{ var drivrName = "oracle.jdbc.driver.OracleDriver" var dsn = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL" var user ="scott" var passwd ="tiger" var db:Db = _ @Before def initialize() { println("Start") db = new Db(drivrName,dsn,user,passwd) } @Test def verifyTable() { // Uses JUnit-style assertions & Uses ScalaTest assertions db.select("*").from("EMP").where("empno >= ?",7700).orderBy("ename") println(db.toString) println(db.getSql) println(" --- Bean SELECTした結果をBEANに格納してArrayで返す") db.executeQuery(classOf[EMP]).foreach({c => println(c.toString) }) println(" --- ColumnNameList") db.getColumnNameList.foreach(c =>{ print(" " + c) }) println db.select("EMPNO,ENAME,HIREDATE").from("EMP").where("empno >= ?",7700).orderBy("EMPNO") println(db.toString) println(db.getSql) println(" --- Bean SELECTした結果をBEANに格納して返すIteratorによる実装。foreachにて出力はXML") db.executeQueryIterator(classOf[EMP]).foreach({c => println(c.toXml) }) println(" --- ColumnNameList") db.getColumnNameList.foreach(c =>{ print(" " + c) }) println db.select("EMPNO,ENAME,HIREDATE").from("EMP").where("empno >= ?",7700).orderBy("EMPNO") println(db.toString) println(db.getSql) println(" --- Bean SELECTした結果をBEANに格納して返すIteratorによる実装。while句でhasNext、next関数にて出力はJson") val it = db.executeQueryIterator(classOf[EMP]) while(it.hasNext){ println(it.next.toJson) } println(" --- ColumnNameList") db.getColumnNameList.foreach(c =>{ print(" " + c) }) println db.select("EMPNO,ENAME,HIREDATE").from("EMP").where("empno >= ?",7700).orderBy("EMPNO") println(db.toString) println(db.getSql) println(" --- Array SELECTした結果をArray[Any]に格納して返すIteratorによる実装。while句でhasNext、next関数にて出力はtoString") val list2 = db.executeQueryIterator while(list2.hasNext){ list2.next.foreach(v =>print(v.toString + " ")) println } println(" --- ColumnNameList") db.getColumnNameList.foreach(c =>{ print(" " + c) }) println println(" --- End Sql") } @After def close() { if(db != null) db.close println("End") } }
テスト結果は、以下の通り。
Start MissingResourceException:Can't find bundle for base name env, locale JDBC Driver:Oracle JDBC driver Version:11.1.0.7.0-Production Database:Oracle Version:11.2 select * from EMP where empno >= ? order by ename [7700] select * from EMP where empno >= ? order by ename --- Bean SELECTした結果をBEANに格納してArrayで返す 7876,ADAMS,CLERK,7788,1987-05-23 00:00:00.0,1100,null,20 7782,CLARK,MANAGER,7839,1981-06-09 00:00:00.0,2450,null,10 7902,FORD,ANALYST,7566,1981-12-03 00:00:00.0,3000,null,20 7900,JAMES,CLERK,7698,1981-12-03 00:00:00.0,950,null,30 7839,KING,PRESIDENT,null,1981-11-17 00:00:00.0,5000,null,10 7934,MILLER,CLERK,7782,1982-01-23 00:00:00.0,1300,null,10 7788,SCOTT,ANALYST,7566,1987-04-19 00:00:00.0,3000,null,20 7844,TURNER,SALESMAN,7698,1981-09-08 00:00:00.0,1500,0,30 --- ColumnNameList EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO [7700] select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO --- Bean SELECTした結果をBEANに格納して返すIteratorによる実装。foreachにて出力はXML <EMP><EMPNO>7782</EMPNO><ENAME>CLARK</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1981-06-09 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7788</EMPNO><ENAME>SCOTT</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1987-04-19 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7839</EMPNO><ENAME>KING</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1981-11-17 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1981-09-08 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7876</EMPNO><ENAME>ADAMS</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1987-05-23 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1981-12-03 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1981-12-03 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> <EMP><EMPNO>7934</EMPNO><ENAME>MILLER</ENAME><JOB></JOB><MGR></MGR><HIREDATE>1982-01-23 00:00:00.000</HIREDATE><SAL></SAL><COMM></COMM><DEPTNO></DEPTNO></EMP> --- ColumnNameList EMPNO ENAME HIREDATE select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO [7700] select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO --- Bean SELECTした結果をBEANに格納して返すIteratorによる実装。while句でhasNext、next関数にて出力はJson {"EMP" : {"EMPNO" : "7782","ENAME" : "CLARK","HIREDATE" : "1981-06-09 00:00:00.0"}} {"EMP" : {"EMPNO" : "7788","ENAME" : "SCOTT","HIREDATE" : "1987-04-19 00:00:00.0"}} {"EMP" : {"EMPNO" : "7839","ENAME" : "KING","HIREDATE" : "1981-11-17 00:00:00.0"}} {"EMP" : {"EMPNO" : "7844","ENAME" : "TURNER","HIREDATE" : "1981-09-08 00:00:00.0"}} {"EMP" : {"EMPNO" : "7876","ENAME" : "ADAMS","HIREDATE" : "1987-05-23 00:00:00.0"}} {"EMP" : {"EMPNO" : "7900","ENAME" : "JAMES","HIREDATE" : "1981-12-03 00:00:00.0"}} {"EMP" : {"EMPNO" : "7902","ENAME" : "FORD","HIREDATE" : "1981-12-03 00:00:00.0"}} {"EMP" : {"EMPNO" : "7934","ENAME" : "MILLER","HIREDATE" : "1982-01-23 00:00:00.0"}} --- ColumnNameList EMPNO ENAME HIREDATE select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO [7700] select EMPNO,ENAME,HIREDATE from EMP where empno >= ? order by EMPNO --- Array SELECTした結果をArray[Any]に格納して返すIteratorによる実装。while句でhasNext、next関数にて出力はtoString 7782 CLARK 1981-06-09 00:00:00.0 7788 SCOTT 1987-04-19 00:00:00.0 7839 KING 1981-11-17 00:00:00.0 7844 TURNER 1981-09-08 00:00:00.0 7876 ADAMS 1987-05-23 00:00:00.0 7900 JAMES 1981-12-03 00:00:00.0 7902 FORD 1981-12-03 00:00:00.0 7934 MILLER 1982-01-23 00:00:00.0 --- ColumnNameList EMPNO ENAME HIREDATE --- End Sql End
コメントを残す
コメントを投稿するにはログインしてください。