web-dev-qa-db-fra.com

Modèle de chaîne correspondant aux meilleures pratiques

Voici le code qui ne fonctionne pas, mais il décrit ce que je veux faire.

Pourriez-vous s'il vous plaît recommander la meilleure approche à ce problème?

def resolveDriver(url: String) = {
  url match {
    case url.startsWith("jdbc:mysql:") => "com.mysql.jdbc.Driver"
    case url.startsWith("jdbc:postgresql:") => "org.postgresql.Driver"
    case url.startsWith("jdbc:h2:") => "org.h2.Driver"
    case url.startsWith("jdbc:hsqldb:") => "org.hsqldb.jdbcDriver"
    case _ => throw new IllegalArgumentException
  }
}
28
Nikita Volkov

En termes de syntaxe, vous pouvez modifier un tout petit peu vos instructions case:

case url if url.startsWith("jdbc:mysql:") => "com.mysql.jdbc.Driver"

Cela lie simplement la valeur url à l'expression de modèle (qui est également url) et ajoute une expression de garde avec un test. Cela devrait faire compiler le code.

Pour le rendre un peu plus scala, vous pouvez retourner une Option [String] (j'ai supprimé une clause couple car c'est juste pour l'illustration):

def resolveDriver(url: String) = url match {
  case u if u.startsWith("jdbc:mysql:") => Some("com.mysql.jdbc.Driver")
  case u if u.startsWith("jdbc:postgresql:") => Some("org.postgresql.Driver")
  case _ => None
}

C'est à moins que vous ne vouliez gérer les exceptions.

42
huynhjl

Voici une autre manière. Stockez tous les mappages dans une carte, puis utilisez la méthode collectFirst pour trouver la correspondance. La signature de type de collectFirst est:

def TraversableOnce[A].collectFirst[B](pf: PartialFunction[A, B]): Option[B]

Usage:

scala> val urlMappings = Map("jdbc:mysql:" -> "com.mysql.jdbc.Driver", "jdbc:postgresql:" -> "org.postgresql.Driver")
urlMappings: scala.collection.immutable.Map[Java.lang.String,Java.lang.String] = Map(jdbc:mysql: -> com.mysql.jdbc.Drive
r, jdbc:postgresql: -> org.postgresql.Driver)

scala> val url = "jdbc:mysql:somestuff"
url: Java.lang.String = jdbc:mysql:somestuff

scala> urlMappings collectFirst { case(k, v) if url startsWith k => v }
res1: Option[Java.lang.String] = Some(com.mysql.jdbc.Driver)
10
missingfaktor

Démarrage Scala 2.13, il est possible de faire correspondre un motif à Strings par en n'appliquant pas d'interpolateur de chaîne :

val s"jdbc:$dialect:$rest" = "jdbc:mysql:whatever"
// dialect: String = "mysql"
// rest: String = "whatever"

Dans notre cas, il s'agit simplement de mapper la valeur extraite (le dialecte sql) au pilote approprié en utilisant un Map:

val drivers = Map(
  "postgresql" -> "org.postgresql.Driver",
  "mysql"      -> "com.mysql.jdbc.Driver",
  "h2"         -> "org.h2.Driver"
)
val driver = drivers(dialect)
// driver: String = "com.mysql.jdbc.Driver"

Si vous attendez des entrées malformées, vous pouvez également utiliser une instruction de correspondance:

"jdbc:postgresql:something" match {
  case s"jdbc:$dialect:$rest" => Some(dialect)
  case _                      => None
}
// Option[String] = Some("postgresql")
3
Xavier Guihot
import PartialFunction._  // condOpt

val drivers = Map( 
  "mysql" -> "mysql driver",
  "h2" -> "h2 driver" 
  // ... 
)
val pattern = "^jdbc:(\\w+):.*".r

def resolveDriver(url: String) = condOpt(url) { 
  case pattern(dbms) => drivers.get(dbms) 
}.flatten.getOrElse(throw new IllegalArgumentException)
0
Volty De Qua