1. Dependencias en [Link].
kts
dependencies {
// H2 Database
implementation("com.h2database:h2:2.3.232")
implementation("com.h2database:h2:2.3.224")
// HikariCP (para pool de conexiones)
implementation("[Link]:HikariCP:5.0.0")
// ORM: Exposed
implementation("[Link]:exposed-core:0.46.1")
implementation("[Link]:exposed-dao:0.46.1")
implementation("[Link]:exposed-jdbc:0.46.1")
}
2. Configuración de conexión
🔹 JDBC (sin Hikari)
class ConexionJDBC {
val conexion: Connection =
[Link]("jdbc:h2:./data/usuariosdb", "sa", "")
}
🔹 Hikari (pool de conexiones)
class PoolHikari {
private val config = HikariConfig().apply {
jdbcUrl = "jdbc:h2:./data/usuariosdb"
driverClassName = "[Link]"
username = "sa"
password = ""
maximumPoolSize = 5
}
private val dataSource = HikariDataSource(config)
val conexion: Connection get() = [Link]
}
🔹 ORM (Exposed)
class ConexionORM {
fun iniciar() {
[Link](
url = "jdbc:h2:./data/usuariosdb",
driver = "[Link]",
user = "sa",
password = ""
)
}
}
3. Crear tabla usuarios (SQL + JDBC)
fun crearTablaUsuarios() {
val sql = """
CREATE TABLE IF NOT EXISTS usuarios (
id INT PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(100),
email VARCHAR(100)
);
""".trimIndent()
ConexionJDBC().[Link] { c ->
[Link]().use { stmt ->
[Link](sql)
}
}
}
4. DAO (Data Access Object)
data class Usuario(val id: Int?, val nombre: String, val email:
String)
interface UsuarioDAO {
fun crear(usuario: Usuario): Usuario
fun obtenerPorId(id: Int): Usuario?
fun actualizar(usuario: Usuario): Boolean
fun eliminar(id: Int): Boolean
fun listarTodos(): List<Usuario>
}
5. Implementación con JDBC + private val c:
Connection
class UsuarioDAOImpl(private val c: Connection) : UsuarioDAO {
override fun crear(usuario: Usuario): Usuario {
val sql = "INSERT INTO usuarios (nombre, email) VALUES (?,
?)"
[Link](sql,
[Link].RETURN_GENERATED_KEYS).use { stmt ->
[Link](1, [Link])
[Link](2, [Link])
[Link]()
val rs = [Link]
if ([Link]()) {
return [Link](id = [Link](1))
}
}
throw Exception("No se pudo crear el usuario")
}
override fun obtenerPorId(id: Int): Usuario? {
val sql = "SELECT * FROM usuarios WHERE id = ?"
[Link](sql).use { stmt ->
[Link](1, id)
val rs = [Link]()
return if ([Link]()) {
Usuario([Link]("id"), [Link]("nombre"),
[Link]("email"))
} else null
}
}
override fun actualizar(usuario: Usuario): Boolean {
val sql = "UPDATE usuarios SET nombre = ?, email = ? WHERE
id = ?"
[Link](sql).use { stmt ->
[Link](1, [Link])
[Link](2, [Link])
[Link](3, [Link]!!)
return [Link]() > 0
}
}
override fun eliminar(id: Int): Boolean {
val sql = "DELETE FROM usuarios WHERE id = ?"
[Link](sql).use { stmt ->
[Link](1, id)
return [Link]() > 0
}
}
override fun listarTodos(): List<Usuario> {
val lista = mutableListOf<Usuario>()
val sql = "SELECT * FROM usuarios"
[Link]().use { stmt ->
val rs = [Link](sql)
while ([Link]()) {
[Link](Usuario([Link]("id"),
[Link]("nombre"), [Link]("email")))
}
}
return lista
}
}
6. Repository Pattern
class UsuarioRepository(private val dao: UsuarioDAO) {
fun registrar(usuario: Usuario): Usuario = [Link](usuario)
fun buscar(id: Int): Usuario? = [Link](id)
fun modificar(usuario: Usuario): Boolean =
[Link](usuario)
fun borrar(id: Int): Boolean = [Link](id)
fun obtenerTodos(): List<Usuario> = [Link]()
}
🏭 7. Factory y AbstractFactory
🔹 Factory
class DAOFactory(private val c: Connection) {
fun crearUsuarioDAO(): UsuarioDAO = UsuarioDAOImpl(c)
}
🔹 Abstract Factory
interface AbstractDAOFactory {
fun getUsuarioDAO(): UsuarioDAO
}
class H2DAOFactory(private val c: Connection) : AbstractDAOFactory {
override fun getUsuarioDAO(): UsuarioDAO = UsuarioDAOImpl(c)
}
8. Uso de prepareStatement, createStatement,
executeUpdate, executeQuery
Ya está incluido en el DAO, pero aquí un resumen:
// INSERT
val insert = "INSERT INTO usuarios (nombre, email) VALUES (?, ?)"
val ps = [Link](insert)
[Link](1, "Juan")
[Link](2, "juan@[Link]")
[Link]()
// SELECT
val select = "SELECT * FROM usuarios"
val stmt = [Link]()
val rs = [Link](select)
while ([Link]()) {
println([Link]("nombre"))
}
9. CRUD de ejemplo (uso real)
fun main() {
crearTablaUsuarios()
val c = PoolHikari().conexion
val dao = UsuarioDAOImpl(c)
val repo = UsuarioRepository(dao)
val nuevo = [Link](Usuario(null, "Ana",
"ana@[Link]"))
println("Creado: $nuevo")
val encontrado = [Link]([Link]!!)
println("Encontrado: $encontrado")
[Link]([Link](nombre = "Ana Modificada"))
println("Modificado: ${[Link]([Link]!!)}")
println("Todos: ${[Link]()}")
[Link]([Link]!!)
println("Eliminado. Todos ahora: ${[Link]()}")
}
1. Conexión ORM (Exposed)
kotlin
CopiarEditar
class ConexionORM {
fun iniciar() {
[Link](
url = "jdbc:h2:./data/usuariosdb",
driver = "[Link]",
user = "sa",
password = ""
)
}
}
🧱 2. Tabla usuarios con Exposed
kotlin
CopiarEditar
class UsuariosTable : IntIdTable("usuarios") {
val nombre = varchar("nombre", 100)
val email = varchar("email", 100)
}
🧩 3. Entidad DAO
kotlin
CopiarEditar
class UsuarioORM(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<UsuarioORM>(UsuariosTable())
var nombre by UsuariosTable().nombre
var email by UsuariosTable().email
}
💾 4. DAO clásico para usar Repository
kotlin
CopiarEditar
interface UsuarioDAOORM {
fun crear(nombre: String, email: String): UsuarioORM
fun obtener(id: Int): UsuarioORM?
fun actualizar(id: Int, nombre: String, email: String): Boolean
fun eliminar(id: Int): Boolean
fun listar(): List<UsuarioORM>
}
🧪 5. Implementación del DAO con Exposed ORM
kotlin
CopiarEditar
class UsuarioDAOImplORM : UsuarioDAOORM {
override fun crear(nombre: String, email: String): UsuarioORM =
transaction {
[Link] {
[Link] = nombre
[Link] = email
}
}
override fun obtener(id: Int): UsuarioORM? = transaction {
[Link](id)
}
override fun actualizar(id: Int, nombre: String, email: String):
Boolean = transaction {
[Link](id)?.let {
[Link] = nombre
[Link] = email
true
} ?: false
}
override fun eliminar(id: Int): Boolean = transaction {
[Link](id)?.let {
[Link]()
true
} ?: false
}
override fun listar(): List<UsuarioORM> = transaction {
[Link]().toList()
}
}
📦 6. Repository con Exposed
kotlin
CopiarEditar
class UsuarioRepositoryORM(private val dao: UsuarioDAOORM) {
fun crear(nombre: String, email: String): UsuarioORM =
[Link](nombre, email)
fun obtener(id: Int): UsuarioORM? = [Link](id)
fun actualizar(id: Int, nombre: String, email: String): Boolean
= [Link](id, nombre, email)
fun eliminar(id: Int): Boolean = [Link](id)
fun listar(): List<UsuarioORM> = [Link]()
}
🧪 7. Ejemplo CRUD completo con ORM
kotlin
CopiarEditar
fun main() {
ConexionORM().iniciar()
// Crear tablas si no existen
transaction {
[Link](UsuariosTable())
}
val dao = UsuarioDAOImplORM()
val repo = UsuarioRepositoryORM(dao)
val nuevo = [Link]("Laura", "laura@[Link]")
println("Creado: ${[Link]} - ${[Link]}")
val obtenido = [Link]([Link])
println("Obtenido: ${obtenido?.nombre}")
[Link]([Link], "Laura Modificada",
"nuevo@[Link]")
println("Modificado: ${[Link]([Link])?.nombre}")
println("Todos: ${[Link]().map { [Link] }}")
[Link]([Link])
println("Después de eliminar: ${[Link]().map { [Link]
}}")
}