Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
airframe-jdbc: Refine JDBC connection pool (#858)
* airframe-jdbc: Redesign connection pool config/interface * Update doc * Fix multiple exceptions * Fix doc
- Loading branch information
Showing
11 changed files
with
296 additions
and
290 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,6 @@ | ||
airframe-jdbc | ||
==== | ||
|
||
airframe-jdbc is a reusable JDBC connection pool implementation with Airframe. | ||
airframe-jdbc is a reusable JDBC connection pool implementation. | ||
|
||
Currently we are supporting these databases: | ||
|
||
- **sqlite**: SQLite | ||
- **postgres**: PostgreSQL (e.g., [AWS RDS](https://aws.amazon.com/rds/)) | ||
|
||
Adding a new connection pool type would be easy. Your contributions are welcome. | ||
|
||
|
||
## Usage | ||
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.wvlet.airframe/airframe-jdbc_2.12/badge.svg)](http://central.maven.org/maven2/org/wvlet/airframe/airframe-jdbc_2.12/) | ||
|
||
**build.sbt** | ||
|
||
```scala | ||
libraryDependencies += "org.wvlet.airframe" %% "airframe-jdbc" % "(version)" | ||
``` | ||
|
||
|
||
```scala | ||
import wvlet.airframe._ | ||
import wvlet.airframe.jdbc._ | ||
|
||
// Import ConnectionPoolFactoryService | ||
trait MyDbTest extends ConnectionPoolFactoryService { | ||
// Create a new connection pool. The created pool will be closed automatically | ||
// after the Airframe session is terminated. | ||
val connectionPool = bind{ config:DbConfig => connectionPoolFactory.newConnectionPool(config) } | ||
|
||
// Create a new database | ||
connectionPool.executeUpdate("craete 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 | ||
connectionPoo.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})") | ||
} | ||
} | ||
} | ||
|
||
... | ||
|
||
// Configuring database | ||
val d = newDesign | ||
// ConnectionPoolFactory should be a singleton so as not to create duplicated pools | ||
.bind[ConnectionPoolFactory].toSingleton | ||
.bind[DbConfig].toInstance(DbConfig.ofSQLite(path="mydb.sqlite")) | ||
|
||
d.withSession { session => | ||
val t = session.build[MyDbTest] | ||
|
||
// You can make queries using the connection pool | ||
t.connectionPool.executeQuery("select ...") | ||
} | ||
// Connection pools will be closed here | ||
|
||
``` | ||
|
||
## Using PostgreSQL | ||
|
||
For using RDS, configure DbConfig as follows: | ||
|
||
```scala | ||
val d = newDesign | ||
.bind[ConnectionPoolFactory].toSingleton | ||
.bind[DbConfig].toInstance( | ||
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: | ||
```scala | ||
val d = newDesign | ||
.bind[ConnectionPoolFactory].toSingleton | ||
.bind[DbConfig].toInstance( | ||
DbConfig.ofPostgreSQL( | ||
host="(your RDS address, e.g., mypostgres.xxxxxx.us-east-1.rds.amazonaws.com)", | ||
database="mydatabase" | ||
) | ||
.withUser("postgres") | ||
.withPassword("xxxxx"), | ||
PostgreSQLConfig(useSSL=false) | ||
) | ||
``` | ||
|
||
## Creating multiple connection pools | ||
|
||
You can create multiple connection pools with different configurations by using type aliases to DbConfig: | ||
|
||
```scala | ||
import wvlet.airframe._ | ||
import wvlet.airframe.jdbc._ | ||
|
||
object MultipleConnection { | ||
type MyDb1Config = DbConfig | ||
type MyDb2Config = DbConfig | ||
} | ||
|
||
import MultipleConnection._ | ||
|
||
trait MultipleConnection extends ConnectionPoolFactoryService { | ||
val pool1 = bind{ c:MyDB1Config => connectionPoolFactory.newConnectionPool(c) } | ||
val pool2 = bind{ c:MyDB2Config => connectionPoolFactory.newConnectionPool(c) } | ||
} | ||
|
||
val d = newDesign | ||
.bind[ConnectionPoolFactory].toSingleton | ||
.bind[MyDb1Config].toInstance(DbConfig.ofSQLite(path="mydb.sqlite")) | ||
.bind[MyDb2Config].toInstance(DbConfig.ofPostgreSQL(database="mydatabase")) | ||
|
||
``` | ||
- [Documentaiton](https://wvlet.org/airframe/docs/airframe-jdbc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
airframe-jdbc/src/main/scala/wvlet/airframe/jdbc/ConnectionPoolFactory.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package wvlet.airframe.jdbc | ||
import wvlet.airframe.control.Control | ||
import wvlet.log.{Guard, LogSupport} | ||
|
||
/** | ||
* A factory for managing multiple connection pools and properly closes these pools upon shutdown | ||
*/ | ||
class ConnectionPoolFactory extends Guard with AutoCloseable with LogSupport { | ||
private var createdPools = List.empty[ConnectionPool] | ||
|
||
/** | ||
* Use this method to add a precisely configured connection pool | ||
* @param pool | ||
* @return | ||
*/ | ||
def addConnectionPool(pool: ConnectionPool): ConnectionPool = { | ||
guard { | ||
// Register the generated pool to the list | ||
createdPools = pool :: createdPools | ||
} | ||
pool | ||
} | ||
|
||
/** | ||
* Add a new connection pool for a specific database | ||
* @param config | ||
* @return | ||
*/ | ||
def newConnectionPool(config: DbConfig): ConnectionPool = { | ||
addConnectionPool(ConnectionPool(config)) | ||
} | ||
|
||
override def close: Unit = { | ||
guard { | ||
Control.closeResources(createdPools: _*) | ||
createdPools = List.empty | ||
} | ||
} | ||
} |
Oops, something went wrong.