JDBC wrapper in a functional manner
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
0
down vote
favorite
I implemented a simple Java JDBC wrapper in Kotlin with Arrow functional library.
/**
* Executes simple SQL statement that takes no arguments.
* E.g. "CREATE TABLE" statement.
*
* @return IO with either an exception or boolean result
*/
fun String.executeStatement(dataSource: DataSource): IO<Either<Throwable, Boolean>>
val connection = dataSource.connection
return IO connection.createStatement().execute(this) .attemptAndCloseConnection(connection)
/**
* Executes prepared SQL statement (a statement that takes arguments).
* E.g. "INSERT, UPDATE, DELETE..." statements.
*
* @return IO with either an exception or with result of execution as an integer
*/
fun String.executePreparedStatement(dataSource: DataSource, vararg args: Any): IO<Either<Throwable, Int>>
val connection = dataSource.connection
return IO
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
preparedStatement.executeUpdate()
.attemptAndCloseConnection(connection)
/**
* Executes SQL query
*/
fun <E> String.executeQuery(dataSource: DataSource, resultSetMapper: (ResultSet) -> E, vararg args: Any): IO<Either<Throwable, List<E>>>
val connection = dataSource.connection
return IO
val list = mutableListOf<E>()
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
val resultSet = preparedStatement.executeQuery()
while (resultSet.next())
list.add(resultSetMapper(resultSet))
list.toList()
.attemptAndCloseConnection(connection)
private fun <A> IO<A>.attemptAndCloseConnection(connection: Connection?) =
this.attempt().map connection?.close(); it
Every result of execution is wrapped in an instance of IO
to represent side-effects.
Functions are invoked directly on strings which produces an instance of Either<Throwable, T>
when run:
val dataSource = HikariDataSource()
// add config for data source...
"""CREATE TABLE cities (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL);""".executeStatement(dataSource)
.unsafeRunSync()
"INSERT INTO cities (name) VALUES (?)".executePreparedStatement(dataSource, "New York").unsafeRunSync()
My major concerns are:
- Passing an instance of
DataSource
upon invocation of every function. E.g. with Scala, I could pass data source implicitly which would declutter invocations. - Mutable list in
executeQuery
function. Is it even ok? - Closing connection (
attemptAndCloseConnection
function) - is there some better way to do this? - Other proposals?
functional-programming kotlin jdbc
add a comment |Â
up vote
0
down vote
favorite
I implemented a simple Java JDBC wrapper in Kotlin with Arrow functional library.
/**
* Executes simple SQL statement that takes no arguments.
* E.g. "CREATE TABLE" statement.
*
* @return IO with either an exception or boolean result
*/
fun String.executeStatement(dataSource: DataSource): IO<Either<Throwable, Boolean>>
val connection = dataSource.connection
return IO connection.createStatement().execute(this) .attemptAndCloseConnection(connection)
/**
* Executes prepared SQL statement (a statement that takes arguments).
* E.g. "INSERT, UPDATE, DELETE..." statements.
*
* @return IO with either an exception or with result of execution as an integer
*/
fun String.executePreparedStatement(dataSource: DataSource, vararg args: Any): IO<Either<Throwable, Int>>
val connection = dataSource.connection
return IO
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
preparedStatement.executeUpdate()
.attemptAndCloseConnection(connection)
/**
* Executes SQL query
*/
fun <E> String.executeQuery(dataSource: DataSource, resultSetMapper: (ResultSet) -> E, vararg args: Any): IO<Either<Throwable, List<E>>>
val connection = dataSource.connection
return IO
val list = mutableListOf<E>()
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
val resultSet = preparedStatement.executeQuery()
while (resultSet.next())
list.add(resultSetMapper(resultSet))
list.toList()
.attemptAndCloseConnection(connection)
private fun <A> IO<A>.attemptAndCloseConnection(connection: Connection?) =
this.attempt().map connection?.close(); it
Every result of execution is wrapped in an instance of IO
to represent side-effects.
Functions are invoked directly on strings which produces an instance of Either<Throwable, T>
when run:
val dataSource = HikariDataSource()
// add config for data source...
"""CREATE TABLE cities (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL);""".executeStatement(dataSource)
.unsafeRunSync()
"INSERT INTO cities (name) VALUES (?)".executePreparedStatement(dataSource, "New York").unsafeRunSync()
My major concerns are:
- Passing an instance of
DataSource
upon invocation of every function. E.g. with Scala, I could pass data source implicitly which would declutter invocations. - Mutable list in
executeQuery
function. Is it even ok? - Closing connection (
attemptAndCloseConnection
function) - is there some better way to do this? - Other proposals?
functional-programming kotlin jdbc
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I implemented a simple Java JDBC wrapper in Kotlin with Arrow functional library.
/**
* Executes simple SQL statement that takes no arguments.
* E.g. "CREATE TABLE" statement.
*
* @return IO with either an exception or boolean result
*/
fun String.executeStatement(dataSource: DataSource): IO<Either<Throwable, Boolean>>
val connection = dataSource.connection
return IO connection.createStatement().execute(this) .attemptAndCloseConnection(connection)
/**
* Executes prepared SQL statement (a statement that takes arguments).
* E.g. "INSERT, UPDATE, DELETE..." statements.
*
* @return IO with either an exception or with result of execution as an integer
*/
fun String.executePreparedStatement(dataSource: DataSource, vararg args: Any): IO<Either<Throwable, Int>>
val connection = dataSource.connection
return IO
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
preparedStatement.executeUpdate()
.attemptAndCloseConnection(connection)
/**
* Executes SQL query
*/
fun <E> String.executeQuery(dataSource: DataSource, resultSetMapper: (ResultSet) -> E, vararg args: Any): IO<Either<Throwable, List<E>>>
val connection = dataSource.connection
return IO
val list = mutableListOf<E>()
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
val resultSet = preparedStatement.executeQuery()
while (resultSet.next())
list.add(resultSetMapper(resultSet))
list.toList()
.attemptAndCloseConnection(connection)
private fun <A> IO<A>.attemptAndCloseConnection(connection: Connection?) =
this.attempt().map connection?.close(); it
Every result of execution is wrapped in an instance of IO
to represent side-effects.
Functions are invoked directly on strings which produces an instance of Either<Throwable, T>
when run:
val dataSource = HikariDataSource()
// add config for data source...
"""CREATE TABLE cities (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL);""".executeStatement(dataSource)
.unsafeRunSync()
"INSERT INTO cities (name) VALUES (?)".executePreparedStatement(dataSource, "New York").unsafeRunSync()
My major concerns are:
- Passing an instance of
DataSource
upon invocation of every function. E.g. with Scala, I could pass data source implicitly which would declutter invocations. - Mutable list in
executeQuery
function. Is it even ok? - Closing connection (
attemptAndCloseConnection
function) - is there some better way to do this? - Other proposals?
functional-programming kotlin jdbc
I implemented a simple Java JDBC wrapper in Kotlin with Arrow functional library.
/**
* Executes simple SQL statement that takes no arguments.
* E.g. "CREATE TABLE" statement.
*
* @return IO with either an exception or boolean result
*/
fun String.executeStatement(dataSource: DataSource): IO<Either<Throwable, Boolean>>
val connection = dataSource.connection
return IO connection.createStatement().execute(this) .attemptAndCloseConnection(connection)
/**
* Executes prepared SQL statement (a statement that takes arguments).
* E.g. "INSERT, UPDATE, DELETE..." statements.
*
* @return IO with either an exception or with result of execution as an integer
*/
fun String.executePreparedStatement(dataSource: DataSource, vararg args: Any): IO<Either<Throwable, Int>>
val connection = dataSource.connection
return IO
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
preparedStatement.executeUpdate()
.attemptAndCloseConnection(connection)
/**
* Executes SQL query
*/
fun <E> String.executeQuery(dataSource: DataSource, resultSetMapper: (ResultSet) -> E, vararg args: Any): IO<Either<Throwable, List<E>>>
val connection = dataSource.connection
return IO
val list = mutableListOf<E>()
val preparedStatement = connection.prepareStatement(this)
args.forEachIndexed() idx, arg -> preparedStatement.setObject(idx + 1, arg)
val resultSet = preparedStatement.executeQuery()
while (resultSet.next())
list.add(resultSetMapper(resultSet))
list.toList()
.attemptAndCloseConnection(connection)
private fun <A> IO<A>.attemptAndCloseConnection(connection: Connection?) =
this.attempt().map connection?.close(); it
Every result of execution is wrapped in an instance of IO
to represent side-effects.
Functions are invoked directly on strings which produces an instance of Either<Throwable, T>
when run:
val dataSource = HikariDataSource()
// add config for data source...
"""CREATE TABLE cities (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL);""".executeStatement(dataSource)
.unsafeRunSync()
"INSERT INTO cities (name) VALUES (?)".executePreparedStatement(dataSource, "New York").unsafeRunSync()
My major concerns are:
- Passing an instance of
DataSource
upon invocation of every function. E.g. with Scala, I could pass data source implicitly which would declutter invocations. - Mutable list in
executeQuery
function. Is it even ok? - Closing connection (
attemptAndCloseConnection
function) - is there some better way to do this? - Other proposals?
functional-programming kotlin jdbc
asked Jul 12 at 11:35
Branislav Lazic
1689
1689
add a comment |Â
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f198358%2fjdbc-wrapper-in-a-functional-manner%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password