Cómo acceder al campo de fecha y hora fuera de una transacción con Kotlin Exposed.
Tengo una configuración expuesta al estilo DAO con una columna datetime
y quiero acceder a ella después de haber recibido la fila del esquema.
Tabla:
object Entries : IntIdTable() {
val date = datetime(name = "date").nullable()
}
Entidad:
class Entry(id: EntityID<Int>) : IntEntity(id) {
companion object : EntityClass<Entry>(Entries)
var date by Entries.date
}
DAO:
object DB {
private val pool = BasicDataSource()
private val database: Database
init {
pool.url = "jdbc:mysql://127.0.0.1:3306/test"
pool.driverClassName = "com.mysql.cj.jdbc.Driver"
pool.username = "user"
pool.password = "secret"
pool.minIdle = 5
pool.maxIdle = 10
database = Database.connect(pool)
}
infix fun <T> query(block: DB.() -> T): T {
return transaction {
block.invoke(this@DB)
}
}
}
Main:
fun main() {
val entry = DB.query {
Entry.all().single() // Solo hay una fila en este punto
}
println(entry.date) //! Se produce un error en esta línea
}
Lanza una excepción java.lang.IllegalStateException: No hay transacción en contexto.
. Cuando muevo el println
dentro de la transacción, funciona como se esperaba. Si cambio el tipo de la columna a varchar
y espero un string
, funciona en ambos casos.
¿Cómo puedo obtener la fecha fuera de la transacción? Creo que funcionaba en algunas versiones anteriores, pero no estoy seguro.
davy.ai
La razón por la que estás obteniendo el error
java.lang.IllegalStateException: No hay transacción en contexto
es porque la propiedaddate
de la entidadEntry
se inicializa de forma perezosa dentro de un contexto de transacción.Cuando llamas a
Entry.all().single()
, se crea la instancia deEntry
, pero sus propiedades aún no están inicializadas. Cuando intentas acceder aentry.date
fuera del contexto de transacción, el método getter de la propiedaddate
intenta acceder a la base de datos, pero no hay un contexto de transacción disponible.Para obtener la fecha fuera de la transacción, puedes hacer lo siguiente:
date
dentro del contexto de transacción:El bloque
.apply { date }
carga la propiedaddate
de la entidadEntry
dentro del contexto de transacción, de manera que se inicializa de forma inmediata antes de que termine la transacción.Inicializar manualmente la propiedad
date
fuera del contexto de transacción:Aquí, estamos obteniendo la entidad
Entry
dentro del contexto de transacción y luego inicializando la propiedaddate
fuera del contexto de transacción. Esto cargará de forma inmediata la propiedaddate
y te permitirá acceder a ella fuera de la transacción.Vale la pena mencionar que aunque la opción 2 funcione, generalmente no se recomienda acceder a propiedades perezosas fuera de un contexto de transacción, ya que puede conducir a comportamientos inesperados y problemas de rendimiento.