【问题标题】:How to create a Scala Jdbc program using Option to handle null while returning connection?如何使用 Option 创建 Scala Jdbc 程序以在返回连接时处理 null?
【发布时间】:2020-02-13 19:13:13
【问题描述】:

我正在尝试编写一个 scala-jdbc 程序,该程序将对我们数据库中存在的表运行分析语句。为此,我编写了如下代码。

object Trip {
    def main(args: Array[String]): Unit = {
        val gs = new GetStats(args(0))
        gs.run_analyze()
    }
}
-----------------------------------------------------------------
class GetStats {
    var tables = ""
    def this(tables:String){
        this
        this.tables = tables
    }
    def run_analyze():Unit = {
        val tabList = tables.split(",")
        val gpc = new GpConnection()
        val con = gpc.getGpCon()
        val statement = con.get.createStatement()
        try {
            for(t<-tabList){
                val rs = statement.execute(s"analyze ${t}")
                if(rs.equals(true)) println(s"Analyzed ${t}")
                else println(s"Analyze failed ${t}")
            }
        } catch {
            case pse:PSQLException => pse.printStackTrace()
            case e:Exception       => e.printStackTrace()
        }
    }
}
-----------------------------------------------------------------
class GpConnection {
    var gpCon: Option[Connection] = None
    def getGpCon():Option[Connection] = {
        val url      = "jdbc:postgresql://.."
        val driver   = "org.postgresql.Driver"
        val username = "user"
        val password = "1239876"
        Class.forName(driver)
            if(gpCon==None || gpCon.get.isClosed) {
            gpCon = DriverManager.getConnection(url, username, password).asInstanceOf[Option[Connection]]
            gpCon
        } else gpCon
    }    
}

我在我的想法 (IntelliJ) 上创建了一个 jar 文件并提交如下 jar。

scala -cp /home/username/jars/postgresql-42.1.4.jar analyzetables_2.11-0.1.jar schema.table

当我提交 jar 文件时,我看到了异常 ClassCastException,如下所示。

java.lang.ClassCastException: org.postgresql.jdbc.PgConnection cannot be cast to scala.Option
    at com.db.manager.GpConnection.getGpCon(GpConnection.scala:15)
    at com.gp.analyze.GetStats.run_analyze(GetStats.scala:19)
    at com.runstats.Trip$.main(Trip.scala:8)
    at com.runstats.Trip.main(Trip.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:98)
    at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:32)
    at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:30)
    at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:98)
    at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:90)
    at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:22)

异常表示无法将连接强制转换为scala.option,但如果我不使用选项,我将无法使用null 来初始化连接对象,并且在运行代码时会看到NullPointerException。 谁能让我知道我在这里犯了什么错误,我该如何解决?

【问题讨论】:

  • 你不能凭空创建Option。试试gpCon = Option(DriverManager.getConnection(...)),顺便说一句,通过asInstanceOf[] 投射是总是一个的主意。
  • 哦,太好了..我进行了更改,并且成功了。你能回答这个问题吗?

标签: scala


【解决方案1】:

asInstanceOf[] 不能这样工作。它不仅会为您创建一个Option[]

val x:Option[Int] = 5.asInstanceOf[Option[Int]]  //not gonna happen

您必须明确创建Option[]

val x:Option[Int] = Option(5)

【讨论】:

    【解决方案2】:

    您可以将未初始化的变量用作:

    var gpCon: Connection = _
    

    但是由于您使用的是scala.util.Option,这是更好的做法,请以函数式方式进行,不要在 Scala 中编写命令式 Java 代码,例如:

    // a singleton object (Scala provided)
    object GpConnection {
        private var gpCon: Option[Connection] = None
    
        // returns a Connection (no option - as we need it!)
        def getOrCreateCon(): Connection = gpCon match {
            case conOpt if conOpt.isEmpty || conOpt.get.isClosed =>
                // connection not present or is closed
                val url      = "jdbc:postgresql://.."
                val driver   = "org.postgresql.Driver"
                val username = "user"
                val password = "1239876"
    
                // may throw an exception - you can even handle this
                Class.forName(driver)
    
                // may throw an exception - you can even handle this
                gpCon = Option(DriverManager.getConnection(url, username, password).asInstanceOf[Connection])
                gpCon.getOrElse(throw new RuntimeException("Cannot create connection"))
            case Some(con) => con
        }    
    }
    

    像这样使用它:

    val con = GpConnection.getOrCreateCon
    

    【讨论】:

      猜你喜欢
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2018-01-14
      • 2011-05-14
      相关资源
      最近更新 更多