Skip to content

Exposed

Gabriel Souza edited this page Aug 5, 2020 · 4 revisions

The Jetbrains Exposed is a great and easy to use library to work with SQL in Kotlin. The library has a typesafe API that make your SQL queries easy and safe to use.

KotlinBukkitAPI provides some extensions and helpers to work easily on a Bukkit Plugin.

The recomendation is to use Exposed + HikariCP to handle your connections pool more effective.

These extensions are provided in the exposed module:

dependencies {
  ...
  implementation("br.com.devsrsouza.kotlinbukkitapi:exposed:0.1.0-SNAPSHOT")
}

Database Helper

The project provides a database helper to easily generate HikariDataSource to be used in the Exposed Database.

First for get a HikariDataSource we will need a DatabaseTypeConfig that will have all the configurations need to KotlinBukkitAPI generate the proper HikariDataSource.

val config = DatabaseTypeConfig(
        type = "H2",
        hostname = "localhost",
        port = 3306,
        database = "kbapi_database",
        user = "root",
        password = "12345"
)

The following database types are supported out of the box with KotlinBukkitAPI.

  • SQLite
  • H2
  • MySQL
  • PostgreSQL
  • SQLServer

All the drivers from the non shipped with Bukkit is downloaded and provided at runtime by KotlinBukkitAPI, you don't need to ship it yourself (H2, PostgreSQL and SQLServer).

Now, we will extract a DatabaseType based on that config, with the DatabaseType we will be able to get the HikariDataSource.

val databaseType = databaseTypeFrom(dataFolder = yourPluginDataFodler, config = config)

val dataSource: HikariDataSource = databaseType.dataSource()

You can also get the HikariConfig if you want to do an optimization by your own: databaseType.config().

Now that we have the DataSource we can work with the Exposed.

val database = Database.connect(dataSource)

transaction(database) {
  SchemaUtils.create(YourTable)
}

DAO Extensions

DAO is a really cool part of the Exposed and KotlinBukkitAPI can't let this without any extensions :D .

Making plugins we have commum types that we want to store, in file, in a database. Exposed make easy to work with database, but, it can get a little boilerplate in a point that you think "there is no better way to do that?".

Let's get the Location example for a minute, we usually store the world, x, y, z, yaw, pitch in different columns and convert it to Location and set a location to the Exposed DAO can be a little boilerplate. For that, we have delegate extensions to work with Bukkit Plugin commum types.

These are the following supported types:

  • Block
  • BlockPos (Just the position without trying to get the World from the Server)
  • Chunk
  • ChunkPos (Just the chunk position without trying to get the World from the Server)
  • Location
  • LocationPos (Just the position without trying to get the World from the Server)
  • OfflinePlayer
  • World
  • Item (NOTE: This does not save NBT and could break version to version, you can build your own copying and changing the serialization/deserialization logic)

Using it at your DAO

object MarketTable : IntIdTable() {
  ...
  val seller = uuid("seller")
  val item = blob("item")
  val customer = uuid("customer").nullable()
  // location
  val world = varchar("world", 50)
  val x = double("x")
  val y = double("y")
  val z = double("z")
  val yaw = float("yaw")
  val pitch = float("pitch")
  ...
}
class MarketItem(id: EntityID<Int>) : IntEntity(id) {
   ...
   var seller by offlinePlayer(MarketTable.seller)
   var item by itemStack(MarketTable.item)
   var customer by nullableOfflinePlayer(MarketTable.customer)
   var location by location(MarketTable.world, MarketTable.x, MarketTable.y, MarketTable.z, MarketTable.yaw, MarketTable.pitch)
   ...
}

Check all DAO extension delegates

Clone this wiki locally