scala-sql is a library designed for scala language and for JDBC-based database access. It aimed to provide a simple and directive API to replace JDBC's complex, low-level, complicated code.
Let's take an example for simple JDBC access:
val conn = DriverManager.getConnection(url, user, password)
val stmt = conn.prepareStatement("select * from users where id = ?")
val userId = 10
try {
stmt.setInt(1, userId)
val rs = stmt.executeQuery()
while(rs.next()){
println(s"""name: ${rs.getString("name")} age: ${rs.getInt("age")}""")
}
}
finally {
stmt.close
}
and how scala-sql help us:
val conn = DriverManager.getConnection(url, user, password)
val userId = 10
conn.eachRow(sql"select * from users where id = $userId") { rs: ResultSet =>
println(s"""name: ${rs.getString("name")} age: ${rs.getInt("age")}""")
}
via this example, we show you some features of scala-sql:
- scala-sql is a simple encapsulation of jdbc api.
- scala-sql enhances java.sql.Connection/javax.sql.DataSource with some method to direct execute SQL statement and return results. you dont need to worry about resource allocate and free yourself.
- scala-sql provide a powerful string interpolation structure sql, which support saffe dynamic sql statement.(no sql inject)
when using JDBC, we need to seperate the dynamic sql stament(having parameter) and paramteries ourself with a lot of setString/setDate/setInt operation, make the code very noisy.
based on Scala's String-Interpolation feature, scala-sql provides a powerful sql"" constructor like:
sql"select * from users where id = ${userId}"
sql"""update users set name = $userName,
email = ${userEmail}
where id = $userId
"""
don't worry about sql-inject security problem here, since the sql string interpolation is not simple String-Concat operation, It's really paramterized dynamic SQL, so this exmaple will really like follows:
val stmt = prepareStatement("select * from users where id = ?")
stmt.setInt(1, userId)
val stmt2 = prepareStatement("update users set name = ?, email = ? where id = ? ")
stmt2.setString(1, userName)
stmt2.setString(2, email)
stmt2.setInt(3, userId)
scala-sql is not an ORM frameworkd or library, it is just a JDBC wrapper. but it still provide some mapping functions.
- mapping a row(ResultSet) as Row object. since ResultSet is a temporary cursor which
will be invalid after cursor move or cursor closed. scala-sql provide a deattached
value object
Row
. theRow
API is so familiar as theResultSet
withgetXXX(index)
orgetXXX(columnName)
methods, your can think thatRow
is a deattachedResultSet
snapshot. - mapping a row as an Java(Scala) POJO. when iterate a query or execute a query as results,
scala-sql support mapping the ResultSet as an Java(Scala) POJO for your convenient.
- basicly, scala-sql follows the Java Beans conversation, so a
name
column will mapped to aname
property(either java'sgetName/setName
or scala'sname/name_=
). - any transient property marked as @transient will be ignored
- when a rename mapping is needed, you need mark a
@Column(name=)
annotation, eg. a columnuser_email
mapping to a propertyuserEmail
, you need mark@Column(name="user_email")
- You can put a
@Table
annotation on the POJO class when it mapps to another table( default the POJO's simple class name) - also, You can put a
@Table(camelToUnderscore=true)
to mark that the POJO follows mapping underscore column name to camel property name. if you have SQL DDL conversation like this, you can put such a annoation to avoid mark each property with@Column
- basicly, scala-sql follows the Java Beans conversation, so a
- if you querys only 1 columns, you can directly mapping the row to a primitive type such as
Int/String/Date/BigDecimal
etc. - scala-sql is a scala library so it provide special support for scala types, so you can using scala.BigDecimal just as java.math.BigDecimal. Be sure, scala.BigDecimal is much simple than jBigDecimal so i would like to advice using scala.BigDeciaml in our works.
scala-sql enhanced java.sql.Connection with useful methods.
execute a update statment, and return the update count(same as jdbc's executeUpdate)
execute a query statement, and iterate the resultset
- mapping each row as TYPE(see
Mapping
). for simple usage, you can usingRow
instead aPOJO
- execute the closure code
doSth
- Since we are iterate the Result, we can direct process the ResultSet without mapping.
so here, the TYPE can be
ResultSet
which maybe best performance.
execute a query and result the resultset.
- mapping each row as TYPE(see
Mapping
). for simple usage, you can usingRow
instead aPOJO
- Since we return a result list, which must be dettaced data, so
ResultSet
is not supported.
execute a query and return a Optional result. either Some(value) if having 1+ rows or None if the query returns no rows.
scala-sql enhanced javax.sql.DataSource, the api is familar as java.sql.Connection. unlike the Connection operations, the DataSource's operation always follows:
- get a connection from datasource
- execute the update/query on the connection
- close the connection(return to datasource).