JDBCコネクションを閉じない

Posted 2010年10月22日 by

Scalaプログラム入門の4章の「関数の楽しみ。JDBCコネクションを閉じる必要がありません」のような、Scalaらしい操作でEmp表をSelectしてみました。


まず、C#のUsingをScalaで定義するためにControlオブジェクトと定義します。

関数を引き数として渡し、tryの中でパラメータ付きで呼び出します。処理が終わるとfinally で引数へcloseメソッドを呼び出します。

using関数を使えばcloseはこのなかで行われます。

object Control {
    def using[A <: {def close():Unit},B](param:A)(f:A => B):B=
    try {
        f(param)
    }finally {
        param.close()
    }
}


次に、Emp表をSelectするEmpオブジェクトを作ります。

object Emp {
    import Control._
    import java.sql.{DriverManager, Connection, Statement, ResultSet,SQLException}
    var jdbcURL = "jdbc:oracle:thin:@192.168.0.105:1521:ORCL"
    var user ="scott"
    var passwd ="tiger"

    def main(args : Array[String]) : Unit = {
         Class.forName("oracle.jdbc.driver.OracleDriver").newInstance()
         try {
            var list = using(DriverManager.getConnection(jdbcURL,user,passwd)) {
                conn => findEmp(conn)
            }
        } catch {
              case e:SQLException => println("Database error "+e)

              case e => {
                println("Some other exception type:")
                e.printStackTrace()
              }
        }
    }
    def findEmp(conn:Connection): Unit =
        using (conn.createStatement){st =>
            using (st.executeQuery("SELECT * FROM EMP")){rs =>
                while (rs.next()){
                 print(rs.getString("empno") + " ")
                 print(rs.getString("ename") + " ")
                 print(rs.getString("job") + " ")
                 print(rs.getString("mgr") + " ")
                 print(rs.getString("hiredate") + " ")
                 print(rs.getString("deptno") + " ")
                 println(rs.getString("sal"))
            }
        }
    }
}


実行結果は、JDBCコネクションで書いたScalaと同じです。

Scala入門第4章のように書く

先のプログラムをScala入門第4章のように書くと、まず、Emp表の値を格納するEmployeeクラスを定義します。

import java.util.Date

class Employee (var empno:Int
        ,var ename:String
        ,var job:String
        ,var mgr:Int
        ,var hiredate:Date
        ,var deptno:Int
        ,var varsal:Int)
{
    def getEmpno = empno
    def getEname = ename
    def getJob = job
    def getMgr = mgr
    def getHiredate = hiredate
    def getDeptno = deptno
    def getVarsal = varsal

    def setEmpno(value:Int):Unit = empno = value
    def setName(value:String) = ename = value
    def setDeptno(value:Int) = deptno = value

    override def toString() =
        "[Employee empno:"+empno+",ename:"+ename+",job:"+job+",mgr:"+mgr+",hiredate:"+hiredate+",deptno:"+deptno+",varsal:"+varsal+"]"
}



先ほど作ったControlオブジェクトにbmapを追加します。

object Control {
    def using[A <: {def close():Unit},B](param:A)(f:A => B):B=
    try {
        f(param)
    }finally {
        param.close()
    }

    import scala.collection.mutable.ListBuffer
    def bmap[T] (test: => Boolean)(block: => T):List[T] = {
        val ret = new ListBuffer[T]
        while(test) ret += block
        ret.toList
    }
}




Bmapを使ってSelectした結果のレコードをListに追加し、foreachで結果を表示します。

object Emp {
    import Control._
    import java.sql.{DriverManager, Connection, Statement, ResultSet,SQLException}
    var jdbcURL = "jdbc:oracle:thin:@192.168.0.105:1521:ORCL"
    var user ="scott"
    var passwd ="tiger"

    def main(args : Array[String]) : Unit = {
         Class.forName("oracle.jdbc.driver.OracleDriver").newInstance()
         var conn:Connection = null
         try {
            conn = DriverManager.getConnection(jdbcURL,user,passwd)
            var list = findEmp(conn)
            list.foreach(l => println(l))
        } catch {
              case e:SQLException => println("Database error "+e)

              case e => {
                println("Some other exception type:")
                e.printStackTrace()
              }
        } finally {
           conn.close()
        }
   }

//    def findEmp(conn:Connection): Unit =
    def findEmp(conn:Connection): List[Employee] =
        using (conn.createStatement){st =>
            using (st.executeQuery("SELECT * FROM EMP")){rs =>
/*            while (rs.next()){
                 print(rs.getString("empno") + " ")
                 print(rs.getString("ename") + " ")
                 print(rs.getString("job") + " ")
                 print(rs.getString("mgr") + " ")
                 print(rs.getString("hiredate") + " ")
                 print(rs.getString("deptno") + " ")
                 println(rs.getString("sal"))
*/
                 bmap(rs.next){
                    new Employee(
                     rs.getInt("empno")
                     ,rs.getString("ename")
                     ,rs.getString("job")
                     ,rs.getInt("mgr")
                     ,rs.getDate("hiredate")
                     ,rs.getInt("deptno")
                     ,rs.getInt("sal")
                 )
            }
        }
    }
}



結果は以下のように出力されます。

[Employee empno:1011,ename:安藤,job:null,mgr:0,hiredate:null,deptno:0,varsal:0]
[Employee empno:7369,ename:SMITH,job:CLERK,mgr:7902,hiredate:1980-12-17,deptno:20,varsal:800]
[Employee empno:7499,ename:ALLEN,job:SALESMAN,mgr:7698,hiredate:1981-02-20,deptno:30,varsal:1600]
[Employee empno:7521,ename:WARD,job:SALESMAN,mgr:7698,hiredate:1981-02-22,deptno:30,varsal:1250]
[Employee empno:7566,ename:JONES,job:MANAGER,mgr:7839,hiredate:1981-04-02,deptno:20,varsal:2975]
[Employee empno:7654,ename:MARTIN,job:SALESMAN,mgr:7698,hiredate:1981-09-28,deptno:30,varsal:1250]
[Employee empno:7698,ename:BLAKE,job:MANAGER,mgr:7839,hiredate:1981-05-01,deptno:30,varsal:2850]
[Employee empno:7782,ename:CLARK,job:MANAGER,mgr:7839,hiredate:1981-06-09,deptno:10,varsal:2450]
[Employee empno:7788,ename:SCOTT,job:ANALYST,mgr:7566,hiredate:1987-04-19,deptno:20,varsal:3000]
[Employee empno:7839,ename:KING,job:PRESIDENT,mgr:0,hiredate:1981-11-17,deptno:10,varsal:5000]
[Employee empno:7844,ename:TURNER,job:SALESMAN,mgr:7698,hiredate:1981-09-08,deptno:30,varsal:1500]
[Employee empno:7876,ename:ADAMS,job:CLERK,mgr:7788,hiredate:1987-05-23,deptno:20,varsal:1100]
[Employee empno:7900,ename:JAMES,job:CLERK,mgr:7698,hiredate:1981-12-03,deptno:30,varsal:950]
[Employee empno:7902,ename:FORD,job:ANALYST,mgr:7566,hiredate:1981-12-03,deptno:20,varsal:3000]
[Employee empno:7934,ename:MILLER,job:CLERK,mgr:7782,hiredate:1982-01-23,deptno:10,varsal:1300]



余白

EmployeeクラスのtoString() のオブジェクトをダンプする文字列を作る行が長いので、’+’のところで改行したら、出力された文字列が改行したところで切れてしまいました。

Post Details

  • Post Title: JDBCコネクションを閉じない
  • Author: admin
  • Filed As: Scala
  • Tags:
  • You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

コメントを残す