Home

cobaltolabs edited this page Nov 3, 2012 · 2 revisions
Clone this wiki locally

Documentation ver 0.1

Changes on 0.1

General

Maven Repositories

The jars will be uploaded to Maven Repositories in the next few weeks… if you want to use right now, just download the jar or clone the repo and build the project

Package names

The package names for KotlinPrimavera start with co.cobaltolabs.kotlin.spring this package name is provisional and will be changed in the next iterations

Data Access with KotlinPrimavera

KotlinPrimavera offer Support classes and extension functions for org.springframework.jdbc.core.JdbcOperations and org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations

Using JdbcOperations with Kotlin

You could use JdbcOperations (org.springframework.jdbc.core.JdbcTemplate is the defualt implementation for JdbcOperations) as always. Ex:

Test public fun testWithRowMapper() {
        assertEquals(template!!.query("select * from users", object:RowMapper<User>{
            public override fun mapRow(rs: ResultSet?, rowNum: Int): User? {
                return User(id = rs!!.getInt("id"),
                        firstName = rs.getString("first_name"),
                        lastName = rs.getString("last_name"),
                        age = rs.getInt("age"))
            }
        })!!.size(), 2)
    }

In the previous example, we're using an anonymous implementation for RowMapper<T>

Going functional

For Every Interface that have only one method, KotlinPrimavera offers a functional implementation that you could use instead of anonymous implementations. Ex:

import co.cobaltolabs.kotlin.spring.jdbc.core.*

Test public fun testWithFunctionalRowMapper() {
        assertEquals(template!!.query("select * from users", FunctionalRowMapper{(rs: ResultSet, rowNum: Int)->
            User(id = rs.getInt("id"),
                    firstName = rs.getString("first_name"),
                    lastName = rs.getString("last_name"),
                    age = rs.getInt("age"))
        })!!.size(), 2)
    }

In the previous example we pass a function (ResultSet,Int)->T as parameter in the FunctionalRowMapper<T> constructor

This is the complete list of functional implementations

Interface Functional implementation Function
CallableStatementCallback<T> FunctionalCallableStatementCallback<T> (CallableStatement)->T
CallableStatementCreator FunctionalCallableStatementCreator (Connection)->CallableStatement
ConnectionCallback<T> FunctionalConnectionCallback<T> (Connection) -> T
ParameterizedPreparedStatementSetter<T> FunctionalParameterizedPreparedStatementSetter<T> (PreparedStatement, T)->Unit
PreparedStatementCallback<T> FunctionalPreparedStatementCallback<T> (PreparedStatement)->T
PreparedStatementCreator FunctionalPreparedStatementCreator (Connection)->PreparedStatement
PreparedStatementSetter FunctionalPreparedStatementSetter (PreparedStatement)->Unit
ResultSetExtractor<T> FunctionalResultSetExtractor<T> (ResultSet)->T
RowCallbackHandler FunctionalResultSetExtractor<Unit> (ResultSet)->Unit
RowMapper<T> FunctionalRowMapper<T> (ResultSet, Int) -> T
StatementCallback<T> FunctionalStatementCallback<T> (Statement)->T

As you can see RowCallbackHandler don't have his own functional implementation but use FunctionalResultSetExtractor<Unit> a nice effect for use high order functions (In fact a FunctionalRowCallbackHandler exists but is deprecated… yes, we have deprecated classes on our first release)

Using extension functions

Functional implementations are a nice round up, but aren't too functional, KotlinPrimavera offers extension functions that accepts function literals as parameters (This functions are located in the co.cobaltolabs.kotlin.spring.jdbc.core namespace). Ex:

import co.cobaltolabs.kotlin.spring.jdbc.core.*

Test public fun testWithFunctionRowMapper() {
        assertEquals(template!!.query("select * from users") {(rs: ResultSet, rowNum: Int)->
            User(id = rs.getInt("id"),
                    firstName = rs.getString("first_name"),
                    lastName = rs.getString("last_name"),
                    age = rs.getInt("age"))
        }.size(), 2)
    }

This is the complete list of extension functions

JdbcOperations Extension Functions Use instead of
``` executeWithConnection(f: (Connection) -> T): T ``` ``` execute(cc: ConnectionCallback?): T? ```
``` executeWithStatement(f: (Statement)->T): T ``` ``` execute(sc: StatementCallback?): T? ```
``` query(sql: String, f: (ResultSet)->T): T ``` ``` query(sql: String?, rse: ResultSetExtractor?): T? ```
``` query(sql: String, f: (ResultSet)->Unit) ``` ``` query(sql: String?, rch: RowCallbackHandler) ```
``` query(sql: String, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, rm: RowMapper?): MutableList? ```
``` queryForObject(sql: String, f: (ResultSet, Int)->T): T ``` ``` queryForObject(sql: String?, rm: RowMapper?): T? ```
``` executeWithConnectionAndPreparedStatement( sc: (Connection)->PreparedStatement, f: (PreparedStatement)->T): T ``` ``` execute( psc: PreparedStatementCreator?, a: PreparedStatementCallback?): T? ```
``` executeWithStringAndPreparedStatement( sql: String, f: (PreparedStatement)->T): T ``` ``` execute( sql: String, a: PreparedStatementCallback?): T? ```
``` query(sc: (Connection)->PreparedStatement, f: (ResultSet)->T): T ``` ``` query( psc: PreparedStatementCreator?, rse: ResultExtractor?): T? ```
``` query(sql: String, pss: (PreparedStatement)->Unit, f: (ResultSet)->T): T ``` ``` query(sql: String?, pss: PreparedStatementSetter?, rse: ResultSetExtractor?): T? ```
``` query(sql: String, args: Array, argTypes: IntArray, f: (ResultSet)->T): T ``` ``` query(sql: String?, args: Array?, argTypes: IntArray?, rse: ResultSetExtractor?): T? ```
``` query(sql: String, args: Array, f: (ResultSet)->T): T ``` ``` query(sql: String?, args: Array?, rse: ResultSetExtractor?): T? ```
``` query(sql: String, f: (ResultSet)->T, vararg args: Any): T ``` ``` query(sql: String?, rse: ResultSetExtractor?, vararg args: Any?): T? ```
``` query(sc: (Connection)->PreparedStatement, f: (ResultSet, Int)->T): List ``` ``` query(sc: PreparedStatementCreator?, rm: RowMapper?): MutableList? ```
``` query(sql: String, ss: (PreparedStatement)->Unit, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, pss: PreparedStatementSetter?, rm: RowMapper?): MutableList? ```
``` query(sql: String, args: Array, argTypes: IntArray, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, args: Array?, argTypes: IntArray?, rm: RowMapper?): MutableList? ```
``` query(sql: String, args: Array, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, args: Array?, rm: RowMapper?): MutableList? ```
``` query(sql: String, f: (ResultSet, Int)->T, vararg args: Any): List ``` ``` query(sql: String?, rm: RowMapper?, vararg args: Any?): MutableList? ```
``` queryForObject(sql: String, args: Array, argTypes: IntArray, f: (ResultSet, Int)->T): T ``` ``` queryForObject(sql: String?, args: Array?, argTypes: IntArray?, rm: RowMapper?): T? ```
``` queryForObject(sql: String, args: Array, f: (ResultSet, Int)->T): T ``` ``` queryForObject(sql: String?, args: Array?, rm: RowMapper?):T? ```
``` queryForObject(sql: String, f: (ResultSet, Int)->T, vararg args: Any): T ``` ``` queryForObject(sql: String?, rm: RowMapper?, vararg args: Any?): T? ```
``` update(f: (Connection)->PreparedStatement): Int ``` ``` update(psc: PreparedStatementCreator?): Int ```
``` update(f: (Connection)->PreparedStatement, keyHolder: KeyHolder): Int ``` ``` update(psc: PreparedStatementCreator? keyHolder: KeyHolder?): Int ```
``` update(sql: String, f: (PreparedStatement)->Unit): Int ``` ``` update(sql: String?, pss: PreparedStatementSetter?): Int ```
``` batchUpdate(sql: String, batchArgs: Collection, batchSize: Int, f: (PreparedStatement, T)->Unit): Array ``` ``` batchUpdate(sql: String?, batchArgs: Collection?, batchSize: Int, ppss: ParameterizedPreparedStatementSetter?): Array? ```
``` executeWithConnectionAndCallableStatement( csc: (Connection)->CallableStatement, f: (CallableStatement)->T): T ``` ``` execute( csc: CallableStatementCreator?, f: CallableStatementCallback ): T? ```
``` executeWithStringAndCallableStatement( sql: String, f: (CallableStatement)->T): T ``` ``` execute( sql: String? f: CallableStatementCallback ): T? ```
``` call( f: (Connection)->CallableStatement, parameters: List): Map ``` ``` call( csc: CallableStatementCreator?, parameters: List?): MutableMap? ```

Working with EmptyResultDataAccessException and nulls

For methods that return one single object, JdbcOperations (and NamedParameterJdbcOperations) never return null but will throw a org.springframework.dao.EmptyResultDataAccessException if the results are empty. Ex:

Test public fun testWithEmptyResult() {
    try{
        template!!.queryForObject("select * from users where id = ?", {(rs: ResultSet, rowNum: Int)->
            User(id = rs.getInt("id"),
                    firstName = rs.getString("first_name"),
                    lastName = rs.getString("last_name"),
                    age = rs.getInt("age"))
        }, -1)
        fail()//Should never reach this line
    }catch(e: EmptyResultDataAccessException){
        //Expected
    }
}

If you want to manage this empty result with a null you can use the function emptyResultToNull<T>(body: ()->T): T?. If the code block that you write inside the function throws a EmptyResultDataAccessException a null will be returned. Ex:

Test public fun testWithEmptyResultToNull() {
    assertNull(
        emptyResultToNull {
            template!!.queryForObject("select * from users where id = ?", {(rs: ResultSet, rowNum: Int)->
                User(id = rs.getInt("id"),
                        firstName = rs.getString("first_name"),
                        lastName = rs.getString("last_name"),
                        age = rs.getInt("age"))
            }, -1)
        })
}

There's also a queryForNullableObject Extension Function that have the same behaviour, returning null if the result is empty

Test public fun testWithNullable() {
        assertNull(
            template!!.queryForNullableObject("select * from users where id = ?", {(rs: ResultSet, rowNum: Int)->
                User(id = rs.getInt("id"),
                        firstName = rs.getString("first_name"),
                        lastName = rs.getString("last_name"),
                        age = rs.getInt("age"))
            }, -1)
        )
    }

Using NamedParameterJdbcOperations

KotlinPrimavera also have Extension Functions for NamedParameterJdbcOperations

NamedParameterJdbcOperations Extension Functions Use instead of
``` execute(sql: String, source: SqlParameterSource, f: (PreparedStatement)->T): T ``` ``` execute(sql: String?, source: SqlParameterSource?, psc: PreparedStatementCallback?): T? ```
``` execute(sql: String, args: Map, f: (PreparedStatement)->T): T ``` ``` execute(sql: String?, args: Map?, psc: PreparedStatementCallback?): T? ```
``` query(sql: String, source: SqlParameterSource, f: (ResultSet)->T): T ``` ``` query(sql: String?, source: SqlParameterSource?, rse: ResultSeetExtractor?): T? ```
``` query(sql: String, args: Map, f: (ResultSet)->T): T ``` ``` query(sql: String?, args: Map?, rse: ResultSeetExtractor?): T? ```
``` query(sql: String, source: SqlParameterSource, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, source: SqlParameterSource?, rm: RowMapper?): MutableList? ```
``` query(sql: String, args: Map, f: (ResultSet, Int)->T): List ``` ``` query(sql: String?, args: Map?, rm: RowMapper?): List? ```
``` queryForObject(sql: String, source: SqlParameterSource, f: (ResultSet, Int)->T): T ``` ``` queryForObject(sql: String?, source: SqlParameterSource?, rm: RowMapper?): T? ```
``` queryForObject(sql: String, args: Map, f: (ResultSet, Int)->T): T ``` ``` queryForObject(sql: String?, args: Map?, rm: RowMapper?): T? ```