Skip to content

Commit 84d58e5

Browse files
committed
Implement JDBC-based DatabaseProvider and DSL utilities for database module
1 parent f488d72 commit 84d58e5

File tree

3 files changed

+171
-1
lines changed
  • database
    • database-api/src/main/kotlin/com/peco2282/devcore/database
    • database-jdbc

3 files changed

+171
-1
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,84 @@
11
package com.peco2282.devcore.database
22

3+
import org.jetbrains.exposed.v1.core.Table
4+
5+
//import org.jetbrains.exposed.sql.Database
6+
//import org.jetbrains.exposed.sql.SchemaUtils
7+
//import org.jetbrains.exposed.sql.Table
8+
//import org.jetbrains.exposed.sql.transactions.transaction
9+
10+
/**
11+
* Marker annotation for Database DSL.
12+
*/
13+
@DslMarker
14+
annotation class DatabaseDsl
15+
16+
/**
17+
* Data class representing the configuration for a database connection.
18+
*
19+
* @property driver The JDBC driver class name.
20+
* @property url The JDBC connection URL.
21+
* @property user The username for the database connection.
22+
* @property password The password for the database connection.
23+
*/
24+
data class DatabaseConfig(
25+
val driver: String,
26+
val url: String,
27+
val user: String = "",
28+
val password: String = ""
29+
)
30+
31+
/**
32+
* Abstract builder class for constructing a [DatabaseProvider].
33+
*/
34+
@DatabaseDsl
35+
abstract class DatabaseBuilder {
36+
/**
37+
* The database configuration.
38+
*/
39+
var config: DatabaseConfig? = null
40+
41+
/**
42+
* The list of tables to be managed by the database.
43+
*/
44+
protected val tables = mutableListOf<Table>()
45+
46+
/**
47+
* Sets the database configuration.
48+
*
49+
* @param config The [DatabaseConfig] object.
50+
*/
51+
fun config(config: DatabaseConfig) {
52+
this.config = config
53+
}
54+
55+
/**
56+
* Sets the database configuration using individual parameters.
57+
*
58+
* @param driver The JDBC driver class name.
59+
* @param url The JDBC connection URL.
60+
* @param user The username for the database connection.
61+
* @param password The password for the database connection.
62+
*/
63+
fun config(driver: String, url: String, user: String = "", password: String = "") {
64+
this.config = DatabaseConfig(driver, url, user, password)
65+
}
66+
67+
/**
68+
* Registers one or more tables to the database.
69+
* These tables will be created or updated upon initialization.
70+
*
71+
* @param table The tables to register.
72+
*/
73+
fun table(vararg table: Table) {
74+
tables.addAll(table)
75+
}
76+
77+
/**
78+
* Builds and returns a [DatabaseProvider] instance.
79+
*
80+
* @return A [DatabaseProvider] configured with the specified parameters.
81+
* @throws IllegalStateException If the database configuration is not specified.
82+
*/
83+
abstract fun build(): DatabaseProvider
84+
}

database/database-jdbc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version = properties["devcore.database.version"] ?: "1.0.0"
22

33
dependencies {
4-
api(project(":adventure"))
4+
api(project(":database:database-api"))
55
implementation("org.jetbrains.exposed:exposed-jdbc:1.0.0")
66
implementation("com.zaxxer:HikariCP:7.0.0")
77
compileOnly(libs.paper.api)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.peco2282.devcore.database.jdbc
2+
3+
import com.peco2282.devcore.database.DatabaseBuilder
4+
import com.peco2282.devcore.database.DatabaseProvider
5+
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.withContext
7+
import org.jetbrains.exposed.v1.core.Transaction
8+
import org.jetbrains.exposed.v1.jdbc.Database
9+
import org.jetbrains.exposed.v1.jdbc.SchemaUtils
10+
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
11+
import java.util.concurrent.CompletableFuture
12+
13+
/**
14+
* Creates a [DatabaseProvider] using JDBC.
15+
*
16+
* @param builder The configuration builder for the database.
17+
* @return A configured [DatabaseProvider] instance.
18+
* @throws IllegalStateException If the database configuration is not specified.
19+
*/
20+
fun createJdbc(builder: DatabaseBuilder.() -> Unit): DatabaseProvider = DatabaseBuilderImpl().apply(builder).build()
21+
22+
/**
23+
* Implementation of [DatabaseBuilder] for JDBC connections.
24+
*/
25+
internal class DatabaseBuilderImpl : DatabaseBuilder() {
26+
/**
27+
* Builds a [DatabaseProvider] with a JDBC connection.
28+
* Connects to the database and initializes the registered tables.
29+
*
30+
* @return A [DatabaseProvider] instance.
31+
* @throws IllegalStateException If the database configuration is not specified.
32+
*/
33+
override fun build(): DatabaseProvider {
34+
val cfg = config ?: throw IllegalStateException("Database config is not specified")
35+
val db = Database.connect(
36+
url = cfg.url,
37+
driver = cfg.driver,
38+
user = cfg.user,
39+
password = cfg.password
40+
)
41+
42+
// Table initialization
43+
transaction(db) {
44+
SchemaUtils.create(*tables.toTypedArray())
45+
}
46+
47+
return DatabaseProviderImpl(db)
48+
}
49+
}
50+
51+
/**
52+
* Default implementation of [DatabaseProvider].
53+
*
54+
* @property database The JetBrains Exposed [Database] instance.
55+
*/
56+
internal class DatabaseProviderImpl(val database: Database) : DatabaseProvider {
57+
/**
58+
* Executes a transaction synchronously.
59+
*
60+
* @param T The return type of the statement.
61+
* @param statement The code to execute within the transaction.
62+
* @return The result of the transaction.
63+
*/
64+
override fun <T> dbQuery(statement: Transaction.() -> T): T = transaction(database, statement = statement)
65+
66+
/**
67+
* Executes a transaction asynchronously using a [CompletableFuture].
68+
*
69+
* @param T The return type of the statement.
70+
* @param statement The code to execute within the transaction.
71+
* @return A [CompletableFuture] that will contain the result of the transaction.
72+
*/
73+
override fun <T> dbQueryAsync(statement: Transaction.() -> T): CompletableFuture<T> = CompletableFuture.supplyAsync {
74+
dbQuery(statement)
75+
}
76+
77+
/**
78+
* Executes a transaction asynchronously using Kotlin coroutines.
79+
* This implementation uses [Dispatchers.IO] for non-blocking I/O.
80+
*
81+
* @param T The return type of the statement.
82+
* @param statement The code to execute within the transaction.
83+
* @return The result of the transaction.
84+
*/
85+
override suspend fun <T> dbQuerySuspend(statement: Transaction.() -> T): T = withContext(Dispatchers.IO) {
86+
dbQuery(statement)
87+
}
88+
}

0 commit comments

Comments
 (0)