Airframe

Airframe

  • Docs
  • Blog
  • Release Notes
  • GitHub

›Utilities

Resources

  • Overview
  • Articles
  • Release Notes
  • Logos

Framework

  • airframe-di: Dependency Injection
  • Airframe RPC
  • airframe-http: Creating REST Service
  • airframe-rx: ReactiveX interface
  • AirSpec: Testing Framework

Core Modules

  • airframe-codec: Schema-On-Read Object Serializer
  • airframe-config: Application Config Flow
  • airframe-control: Retry/Rate Control
  • airframe-log: Application Logger
  • airframe-metrics: Human-Friendly Measures for Time and Data Size
  • airframe-surface: Object Shape Inspector

Utilities

  • airframe-benchmark: JMH Benchmark
  • airframe-canvas: Off-Heap Memory Manager
  • airframe-fluentd: Fluentd Logger
  • airframe-http-recorder: Web Request/Response Recorder
  • airframe-jdbc: JDBC Connection Pool
  • airframe-jmx: JMX Application Monitor
  • airframe-json: Pure-Scala JSON Parser
  • airframe-launcher: Command-Line Program Launcher
  • airframe-msgpack: Pure-Scala MessagePack Parser
  • airframe-parquet: Parquet Columnar File Reader and Writer
  • airframe-sql: SQL Parser
  • airframe-ulid: ULID Generator

airframe-jdbc: JDBC Connection Pool

airframe-jdbc is a reusable JDBC connection pool implementation with Airframe.

Currently we are supporting these databases:

  • sqlite: SQLite
  • duckdb: DuckDB
  • postgres: PostgreSQL (e.g., AWS RDS)
  • Generic JDBC drivers

airframe-jdbc is wrapping HikariCP jdbc connection pool for Scala.

Usage

Maven Central

build.sbt

libraryDependencies += "org.wvlet.airframe" %% "airframe-jdbc" % "(version)"

The basic usage is creating a new connection pool factory with ConnectionPool.newFactory, then pass database configuration DbConfig to connectionPoolFactory.newConnectionPool(dbConfig):

import wvlet.airframe.jdbc._


// Create a new connection pool. The created pool will be closed when closing this factory.
val factory = ConnectionPool.newFactory

val dbConfig = DbConfig.ofSQLite(path = "mydb.sqlite")
val connectionPool = factory.newConnectionPool(dbConfig)

// Create a new database
connectionPool.executeUpdate("create table if not exists test(id int, name text)")
// Update the database with prepared statement
connectionPool.updateWith("insert into test values(?, ?)") { ps =>
  ps.setInt(1, 1)
  ps.setString(2, "name")  
}

// Read ResultSet
connectionPool.executeQuery("select * from test") { rs =>
  // Traverse the query ResultSet here
  while (rs.next()) {
    val id   = rs.getInt("id")
    val name = rs.getString("name")
    println(s"read (${id}, ${name})")
  }
}

// Close the created connection pools
factory.close()

Using DuckDB

DuckDB is a tiny embedded OLAP database, which can read CSV, JSON, Parquet (columnar file format), etc.

import scala.util.Using

Using.resource(DbConfig.ofDuckDB().newConnectionPool) { pool =>
   pool.query("select id, name from `sample.parquet`") { rs =>
     val id = rs.getInt(1)
     val name = rs.getString(2)
     // ...
   }
}

Using PostgreSQL

For using RDS, configure DbConfig as follows:

DbConfig.ofPostgreSQL(
  host="(your RDS address, e.g., mypostgres.xxxxxx.us-east-1.rds.amazonaws.com)",
  database="mydatabase"
)
.withUser("postgres")
.withPassword("xxxxx")

For accessing a local PostgreSQL without SSL support, disable SSL access like this:

DbConfig.ofPostgreSQL(
  host="(your RDS address, e.g., mypostgres.xxxxxx.us-east-1.rds.amazonaws.com)",
  database="mydatabase"
)
.withUser("postgres")
.withPassword("xxxxx"),
.withPostgreSQLConfig(PostgreSQLConfig(useSSL=false))

Configure HikariCP Connection Pool

To add more configurations to the connection pool, use `withHikariConfig(...):

DbConfig().withHikariConfig { (c: HikariConfig) =>
  // Add your configurations for HikariConfig 
  c.setIdleTimeout(...)
  c
}

The basic configurations (e.g., jdbc driver name, host, port, user, password, etc.) are already set, so you don't need to add them in withHikariConfig.

Using with Airframe DI


val d = newDesign
  .bind[DbConfig].toInstance(DbConfig(...))
  .bind[ConnectionPool].toProvider { (f:ConnectionPoolFactory, dbConfig:DbConfig) => f.newConnectionPool(dbConfig) }

d.build[ConnectionPool] { connectionPool =>
  // You can make queries using the connection pool
  connectionPool.executeQuery("select ...")
}
// Connection pools will be closed here

Creating Multiple Connection Pools

You can create multiple connection pools with different configurations by using type aliases to DbConfig:

import wvlet.airframe._
import wvlet.airframe.jdbc._

object MultipleConnection {
  type MyDb1Config = DbConfig
  type MyDb2Config = DbConfig 
}

import MultipleConnection._

class MultipleConnection(f:ConnectionPoolFactory, c1:MyDB1Config, c2: MyDB2Config) {
  val pool1 = f.newConnectionPool(c1)
  val pool2 = f.newConnectionPool(c2) 
}

val d = newDesign
  .bind[MyDb1Config].toInstance(DbConfig.ofSQLite(path="mydb.sqlite"))
  .bind[MyDb2Config].toInstance(DbConfig.ofPostgreSQL(database="mydatabase"))
  
d.build[MultipleConnection] { c => ... }
// connections will be closed after the DI session closes   
← airframe-http-recorder: Web Request/Response Recorderairframe-jmx: JMX Application Monitor →
  • Usage
    • Using DuckDB
    • Using PostgreSQL
    • Configure HikariCP Connection Pool
  • Using with Airframe DI
    • Creating Multiple Connection Pools
Airframe
Docs
Documentation
Community
Gitter Chat
More
GitHubStar
airframe logo
Copyright © 2024 wvlet.org