我该如何在Scala中连接PostgreSQL数据库?

30

我想知道如何在scala中完成以下事项?

  1. 连接到postgreSQL数据库。
  2. 编写SQL查询,例如SELECT,UPDATE等,以修改该数据库中的表。

我知道在python中可以使用PygreSQL来完成,但在scala中如何做呢?

7个回答

21

您需要在build.sbt中添加依赖项"org.postgresql" % "postgresql" % "9.3-1102-jdbc41",然后可以修改以下代码来连接和查询数据库。用您的数据库用户名替换DB_USER,用您的数据库名称替换DB_NAME。

import java.sql.{Connection, DriverManager, ResultSet}

object pgconn extends App {
  println("Postgres connector")

  classOf[org.postgresql.Driver]
  val con_st = "jdbc:postgresql://localhost:5432/DB_NAME?user=DB_USER"
  val conn = DriverManager.getConnection(con_str)
  try {
    val stm = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)

    val rs = stm.executeQuery("SELECT * from Users")

    while(rs.next) {
      println(rs.getString("quote"))
    }
 } finally {
     conn.close()
  }
}

17
我会建议看一下Doobie这里的“Doobie之书”章节,可以很好地展现如果使用这个库,您的代码会是什么样子。
如果您对 Scala 的纯函数编程方面感兴趣,即 scalaz, scalaz-stream(很可能还有fs2cats),以及一般的引用透明性,则目前这个库是解决这个问题的首选。
值得注意的是,Doobie 不是 ORM。在其核心,它只是 JDBC 上更好、更高级别的 API。

16

请查看教程"使用Scala和JDBC连接MySQL",更改数据库URL并添加正确的JDBC库。链接已损坏,以下是博客内容:

使用Scala和JDBC连接MySQL

介绍如何使用JDBC将Scala连接到MySQL数据库。虽然Scala有许多数据库库,但我发现大多数都无法正常工作。我尝试过scala.dbc、scala.dbc2、Scala Query和Querulous,但它们要么不支持,要么具有非常有限的特性集,或者会将SQL抽象成奇怪的伪语言。

Play框架有一个新的数据库库叫做ANorm,它试图保持与基本SQL的接口,但具有稍微改进的Scala接口。对于我来说,还没有得出结论,只在一个项目中很少使用过。此外,我只看到它在Play应用程序中运行,似乎不容易被轻松地提取出来。

所以我最终选择了基本的Java JDBC连接,结果证明这是一个相当简单的解决方案。

以下是使用Scala和JDBC访问数据库的代码。您需要更改连接字符串参数并修改查询以适应您的数据库。此示例针对MySQL,但任何Java JDBC驱动程序都应该与Scala工作相同。

基本查询

import java.sql.{Connection, DriverManager, ResultSet};

// Change to Your Database Config
val conn_str = "jdbc:mysql://localhost:3306/DBNAME?user=DBUSER&password=DBPWD"

// Load the driver
classOf[com.mysql.jdbc.Driver]

// Setup the connection
val conn = DriverManager.getConnection(conn_str)
try {
    // Configure to be Read Only
    val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)

    // Execute Query
    val rs = statement.executeQuery("SELECT quote FROM quotes LIMIT 5")

    // Iterate Over ResultSet
    while (rs.next) {
        println(rs.getString("quote"))
    }
}
finally {
    conn.close
}

您需要下载mysql-connector jar包。

如果您正在使用maven,可以使用pom片段加载mysql连接器,但需要检查最新版本是什么。

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.12</version>
</dependency>

要运行这个例子,将以下内容保存到一个文件(query_test.scala)中,并使用以下命令运行,同时指定连接器jar的类路径:

scala -cp mysql-connector-java-5.1.12.jar:. query_test.scala

插入、更新和删除

执行插入、更新或删除操作时,需要创建一个可更新的语句对象。执行命令有些不同,并且您很可能希望使用某些参数。以下是使用jdbc和scala进行带参数插入的示例:

// create database connection
val dbc = "jdbc:mysql://localhost:3306/DBNAME?user=DBUSER&password=DBPWD"
classOf[com.mysql.jdbc.Driver]
val conn = DriverManager.getConnection(dbc)
val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)

// do database insert
try {
  val prep = conn.prepareStatement("INSERT INTO quotes (quote, author) VALUES (?, ?) ")
  prep.setString(1, "Nothing great was ever achieved without enthusiasm.")
  prep.setString(2, "Ralph Waldo Emerson")
  prep.executeUpdate
}
finally {
  conn.close
}

23
问题不是如何连接到PostgreSQL吗? - Vincil Bishop

3
我们正在使用Squeryl,到目前为止对我们来说运作良好。根据您的需求,它可能会起作用。
这是支持的数据库listadapters列表。

2
如果你想/需要编写自己的SQL,但讨厌JDBC接口,可以看看O/R Broker。请看这里

1
该链接目前已损坏。 - jedesah
2
我想知道SO是否提供“五年或更长时间后更正损坏链接”的徽章。我猜是“长期维护”徽章。再加一分。我本来会称其为“Go for Broker”。 - som-snytt

1

我建议使用Quill查询库。这里有李昊一的介绍文章,可以帮助你入门。

简而言之

{
    import io.getquill._
    import com.zaxxer.hikari.{HikariConfig, HikariDataSource}
    val pgDataSource = new org.postgresql.ds.PGSimpleDataSource()
    pgDataSource.setUser("postgres")
    pgDataSource.setPassword("example")
    val config = new HikariConfig()
    config.setDataSource(pgDataSource)
    val ctx = new PostgresJdbcContext(LowerCase, new HikariDataSource(config))
    import ctx._
}

定义一个名为ORM的类:

// mapping `city` table
case class City(
    id: Int,
    name: String,
    countryCode: String,
    district: String,
    population: Int
)

查询所有项目:

@ ctx.run(query[City])
cmd11.sc:1: SELECT x.id, x.name, x.countrycode, x.district, x.population FROM city x
val res11 = ctx.run(query[City])
                   ^

res11: List[City] = List(
  City(1, "Kabul", "AFG", "Kabol", 1780000),
  City(2, "Qandahar", "AFG", "Qandahar", 237500),
  City(3, "Herat", "AFG", "Herat", 186800),
...

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接