If you want to see a relatively simple Scala ScalikeJdbc example that performs SQL SELECT
and UPDATE
commands, I hope this example is helpful.
The background for this example goes like this:
- I have a couple of old websites running Drupal 6
- Drupal 6 has been discontinued and is now a security risk
- It’s not worth trying to upgrade them to Drupal 8 (upgrading isn’t easy)
- As a result, I decided to (a) keep the old Drupal 6 database and (b) write a Play Framework application to replace Drupal 6 (which I currently call “Scrupal6”)
- As I started working on this I discovered that a database table named
url_alias
has a wonky setup, where a “node id” value I want to do a join on is embedded inside a varchar field - To make my life easier I decided to write the Scala code shown below to populate a
nid
(node id) field I added to that table - After I issued an
ALTER TABLE
statement to add thenid
field to theurl_alias
table, its schema looks like this:
mysql> desc url_alias;
+----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+----------------+
| pid | int(10) unsigned | NO | PRI | NULL | auto_increment |
| src | varchar(128) | NO | MUL | | |
| dst | varchar(128) | NO | MUL | | |
| language | varchar(12) | NO | | | |
| nid | int(10) unsigned | YES | MUL | NULL | |
+----------+------------------+------+-----+---------+----------------+
Before I run the Scala application below, some sample data from that table looks like this:
| 3717 | node/901 | 2017/06/17/riding-the-wave | | NULL |
| 3718 | node/901/feed | 2017/06/17/riding-the-wave/feed | | NULL |
| 3736 | node/902 | 2017/07/28/wondering-if-its-best-say-nothing | | NULL |
| 3737 | node/902/feed | 2017/07/28/wondering-if-its-best-say-nothing/feed | | NULL |
The purpose of the Scala code below is to put 901
in the last column of the first row (the one with node/901
in the second column), and 902
in the last column of the third row (the one with node/902
in the second column).
The Scala + ScalikeJdbc code
Given that background, here’s the Scala code I wrote to populate the last column in all of the node/XXX
rows, while also skipping all of the node/XXX/feed
rows:
import scalikejdbc._
/**
* Purpose: Populate the new `nid` column in the Drupal 6 `url_alias` table.
*/
object Scrupal6NidPopulator extends App {
// initialize JDBC driver & connection pool. the database is MySQL running under MAMP.
Class.forName("com.mysql.jdbc.Driver")
ConnectionPool.singleton("jdbc:mysql://localhost:8889/scrupal", "root", "root")
// ad-hoc session provider on the REPL
implicit val session = AutoSession
// get all the `url_alias` rows as a List of Map values.
// (note: i could have been smarter about how i wrote this query.)
val entities: List[Map[String, Any]] = sql"select * from url_alias"
.map(_.toMap)
.list
.apply()
// populate the `nid` column in the `url_alias` table when you find
// (a) a "node" entry where (b) that entry isn’t a "node/xxx/feed" entry.
for {
e <- entities
srcField = e("src").toString
if srcField.startsWith("node/") // a guard condition
if !srcField.contains("/feed") // a second guard
} {
val pid = e("pid").toString.toInt
val nidOption = getNodeNumberFromSrcUri(srcField)
nidOption match {
case None => //nada
case Some(nid) => {
// this is a valid `node/xxx` row, so update the `nid` column
sql"update url_alias set nid=${nid} where pid=${pid}".update.apply()
}
}
}
private def getNodeNumberFromSrcUri(srcUriFromDb: String): Option[Int] = {
if (srcUriFromDb.startsWith("node/")) {
// this is the "happy path" use case
toIntOption(srcUriFromDb.drop(5)) //"249" -> 249
} else {
None
}
}
private def toIntOption(s: String): Option[Int] = {
try {
Some(s.toInt)
} catch {
case _: Throwable => None
}
}
}
Discussion
In retrospect some of that code could have been smarter, but a few good things about it are:
- It shows how to perform SQL
SELECT
andUPDATE
queries with ScalikeJdbc - More generally it shows how to connect to a MySQL database with ScalikeJdbc
- It shows how to write a couple of guard conditions in the for-expression
- If you’ve never used it before, there’s some Option/Some/None stuff in there
After I run this code the url_alias
table now looks like this:
| 3717 | node/901 | 2017/06/17/riding-the-wave | | 901 |
| 3718 | node/901/feed | 2017/06/17/riding-the-wave/feed | | NULL |
| 3736 | node/902 | 2017/07/28/wondering-if-its-best-say-nothing | | 902 |
| 3737 | node/902/feed | 2017/07/28/wondering-if-its-best-say-nothing/feed | | NULL |
Notice that the 901 and 902 values have been added to the last column of the table for the appropriate rows.
There’s probably some way to do the same thing using only SQL queries, but SQL isn’t one of my strengths, and I wanted to experiment with ScalikeJdbc anyway.
The build.sbt file
As a final note, here’s the SBT build.sbt file I used on this project:
name := "ScalikeJdbcExamples"
version := "1.0"
scalaVersion := "2.12.4"
libraryDependencies ++= Seq(
"org.scalikejdbc" %% "scalikejdbc" % "3.1.0",
"org.scalikejdbc" %% "scalikejdbc-config" % "3.1.0",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"mysql" % "mysql-connector-java" % "5.1.46"
)
scalacOptions += "-deprecation"
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Summary
As a brief summary, if you wanted to see an example of how to do some Scala/database work with ScalikeJdbc, I hope this example is helpful.