Kotlin works with JDK’s JDBC API. Once we obtain a connection to the database, we can get an instance of Statement. The Statement interface lets us work directly with the database and more importantly, allows us to send queries to the database. This post demonstrates how to use Statement to create a table, insert rows into it, query the table, and truncate it.
Create a Table
Our first operation is to create a table.
fun createTable(connection: Connection, scheme : String, table : String) { //SQL statement to create a table val sql = """ CREATE TABLE $schema.$table ( ID int primary key, ITEM varchar(255), PRICE float) """.trimMargin() with(connection) { //Get and instance of statement from the connection and use //the execute() method to execute the sql createStatement().execute(sql) //Commit the change to the database commit() } }
Kotlin’s triple quoted strings come in handy when writing SQL code. In this example, we use Kotlin’s string template feature to insert the schema and table name. The rest of the SQL defines the columns and the data types used in each column. Next, we obtain an instance of Statement by calling connection.createStatement(). The Statement object has an execute() method which takes a SQL string. Finally, we call commit() on the connection to commit the changes to the DB.
Truncate Table
We can also use the Statement interface to truncate a table.
fun truncateTable(connection: Connection, schema : String, table : String) { val sql = "TRUNCATE TABLE $schema.$table" with (connection) { createStatement().execute(sql) commit() } }
The workflow for truncating a table is the same as creating one. We define a string of SQL. The we obtain an instance of Statement using createStatement() and then pass the SQL to the execute() method on Statement. Then we call commit() on the connection.
Insert Rows
The Statement interface may also be used to insert rows into a table.
fun insertRow(connection: Connection, schema : String, table : String, id: Int, name: String, price: Double) { val sql = "INSERT INTO $schema.$table VALUES ($id, $name, $price)" with(connection) { createStatement().execute(sql) commit() } }
As in all other cases, we can easily use Kotlin’s String templating features to easily build a SQL string. Once again, we use Statement’s execute() method and then commit the changes when the method returns.
Query a Table
Our final example involves using the Statement object to query a table.
fun queryRows(connection: Connection, schema : String, table : String) { val sql = "SELECT * FROM $schema.$table" val rs = connection.createStatement().executeQuery(sql) while (rs.next()) { println("ID: ${rs.getInt("ID")}\t" + "PRICE: $${rs.getDouble("PRICE")}\t" + "NAME: ${rs.getString("ITEM")}") } }
In this case, we need to use the executeQuery() method found on Statement. The executeQuery() returns a ResultSet object, which is used to navigate the records returned from the query. Here are a few of the more useful methods used for navigation.
beforeFirst() | Move the cursor to the first row in the result set |
afterLat() | Navigate to tend of the result set |
absolute(rowNumber : Int) : Boolean | Move to the absolute position of the result set specified by index |
relative(rowNumber : Int) : Boolean | Move the cursor relatively |
next() : Boolean | Move to the next row |
previous() : Boolean | Move to the previous row |
Once we have moved our result set ot the proper row, we can use it to retreive the data from the columns. We have methods such as getString(Int)
, getInt(Int)
, etc. that returns values as their correct data types specified by column index number (1 based). All of these methods also have overloaded methods that allow using the column name rather than the index of the column.
It’s worth noting that in the example above, we use the next() method on result set to setup a while loop that terminates when next() returns false. This allows use to navigate through the entire result set one row at a time.
Putting it Together
Below is an entire Kotlin program that demonstrates the above concepts on an embedded derby database.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>OCJP-DB</groupId> <artifactId>ocjpdb</artifactId> <version>1.0-SNAPSHOT</version> <properties> <kotlin.version>1.2.0</kotlin.version> <main.class>stonesoupprogramming.MainKt</main.class> </properties> <dependencies> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.14.1.0</version> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib-jre8</artifactId> <version>${kotlin.version}</version> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-test</artifactId> <version>${kotlin.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <sourceDirectory>src/main/kotlin</sourceDirectory> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <phase>test-compile</phase> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <configuration> <jvmTarget>1.8</jvmTarget> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>${main.class}</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <phase>test</phase> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>${main.class}</mainClass> </configuration> </plugin> </plugins> </build> </project>
BurgerMenu.kt
package stonesoupprogramming import java.sql.Connection import java.sql.DriverManager import java.util.* private const val SCHEMA = "BURGERS" private const val TABLE = "MENU" fun main(args: Array<String>) { val properties = Properties() //Populate the properties file with user name and password with(properties) { put("user", "admin") put("password", "pw") } //Open a connection to the database DriverManager .getConnection("jdbc:derby:stonesoup;create=true", properties) .use { connection -> prepareTable(connection) insertItems(connection) queryRows(connection) } } private fun queryRows(connection: Connection) { val sql = "SELECT * FROM $SCHEMA.$TABLE" val rs = connection.createStatement().executeQuery(sql) while (rs.next()) { println("ID: ${rs.getInt("ID")}\t" + "PRICE: $${rs.getDouble("PRICE")}\t" + "NAME: ${rs.getString("ITEM")}") } } private fun insertItems(connection: Connection) { insertRow(connection, 1, "'New Bacon-ings'", 5.95) insertRow(connection, 2, "'Chorizo Your Own Adventure Burger'", 5.95) insertRow(connection, 3, "'Not If I Can Kelp It Burger'", 5.95) insertRow(connection, 4, "'The Longest Chard Burger'", 5.95) insertRow(connection, 5, "'Peas and Thank You Burger'", 5.95) insertRow(connection, 6, "'Cole came, cole slaw, cole conquered burger'", 5.95) insertRow(connection, 7, "'Chili Wonka Burger'", 5.95) insertRow(connection, 8, "'The Clear and Present Ginger Burger'", 5.95) } private fun insertRow(connection: Connection, id: Int, name: String, price: Double) { val sql = "INSERT INTO $SCHEMA.$TABLE VALUES ($id, $name, $price)" with(connection) { createStatement().execute(sql) commit() } } private fun prepareTable(connection: Connection) { val metaData = connection.metaData val rs = metaData.getTables(null, SCHEMA, TABLE, null) if (!rs.next()) { createTable(connection) } else { truncateTable(connection) } } private fun truncateTable(connection: Connection) { val sql = "TRUNCATE TABLE $SCHEMA.$TABLE" with (connection) { createStatement().execute(sql) commit() } } private fun createTable(connection: Connection) { //SQL statement to create a table val sql = """ CREATE TABLE $SCHEMA.$TABLE ( ID int primary key, ITEM varchar(255), PRICE float) """.trimMargin() with(connection) { //Get and instance of statement from the connection and use //the execute() method to execute the sql createStatement().execute(sql) //Commit the change to the database commit() } }
2 thoughts on “Kotlin JDBC Create, Insert, Query, and Truncate Tables”