在我的ktor
网络应用中,我正在使用exposed sql
将对象存储在数据库中。
我还使用ehcache
将一些工作从数据库转移到缓存中。
我希望能够更新缓存中的对象,而不必同时更新数据库中的对象(因为它会经常发生)。
我担心的是,当从缓存中逐出对象时,所做的更改将不会保存在数据库中
如何保存对对象所做的更改而不必每次都访问数据库?
MyObject.kt
import kotlinx.css.Color
import java.io.Serializable
data class MyObject(val ID: Int, val userID: String, var description: String, var color: Color, var count: Long = 0) : Serializable
MyObjects.kt
import org.jetbrains.exposed.sql.Table
object MyObjects : Table() {
val ID = integer("ID").primaryKey().autoIncrement()
val count = long("Count")
val userID = varchar("UserID", 64).index()
val color = varchar("Color", 16)
val description = varchar("Description", 128)
}
DAOFacade.kt
import kotlinx.css.Color
import kotlinx.io.core.Closeable
interface DAOFacade : Closeable {
fun getMyObject(ID: Int): MyObject?
fun updateMyObject(ID: Int, description: String? = null, color: Color? = null, count: Long? = null)
}
DAOFacadeDatabase.kt
import kotlinx.css.Color
import org.jetbrains.exposed.sql.*
class DAOFacadeDatabase(private val DB: Database = Database.Companion.connect("jdbc:h2:mem:test", "org.h2.Driver")) : DAOFacade {
init {
DB.transaction { create(MyObjects) }
}
private fun ResultRow.toMyObject() = MyObject(this[MyObjects.ID], this[MyObjects.userID], this[MyObjects.description], Color(this[MyObjects.color]), this[MyObjects.count])
override fun getMyObject(ID: Int): MyObject? = DB.transaction {
MyObjects.select { MyObjects.ID eq ID }.singleOrNull()?.toMyObject()
}
override fun updateMyObject(ID: Int, description: String?, color: Color?, count: Long?): Unit = DB.transaction {
MyObjects.update({ MyObjects.ID eq ID }) {
if (description != null) it[MyObjects.description] = description
if (color != null) it[MyObjects.color] = color.value
if (count != null) it[MyObjects.count] = count
}
}
override fun close() = Unit
DAOFacadeCache.kt
import kotlinx.css.Color
import org.ehcache.CacheManagerBuilder
import org.ehcache.config.CacheConfigurationBuilder
import org.ehcache.config.ResourcePoolsBuilder
import org.ehcache.config.persistence.CacheManagerPersistenceConfiguration
import org.ehcache.config.units.EntryUnit
import org.ehcache.config.units.MemoryUnit
import java.io.File
class DAOFacadeCache(private val delegate: DAOFacade, storage: File) : DAOFacade {
private val myObjectCacheAlias = "MyObject Cache"
private val cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.with(CacheManagerPersistenceConfiguration(storage))
.withCache(myObjectCacheAlias, CacheConfigurationBuilder.newCacheConfigurationBuilder<Int, MyObject>()
.withResourcePools(
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(1024, EntryUnit.ENTRIES)
.offheap(16, MemoryUnit.MB)
.disk(128, MemoryUnit.MB, true)
)
.buildConfig(Int::class.javaObjectType, MyObject::class.java)
).build(true)
private val myObjectCache = cacheManager.getCache(myObjectCacheAlias, Int::class.javaObjectType, MyObject::class.java)
override fun getMyObject(ID: Int): MyObject? = myObjectCache[ID].takeUnless { it == null } ?: delegate.getMyObject(ID)?.also {
myObjectCache.put(ID, it)
}
override fun updateMyObject(ID: Int, description: String?, color: Color?, count: Long?) {
getMyObject(ID)?.let {
if (description != null) it.description = description
if (color != null) it.color = color
if (count != null) it.count = count
}
}
override fun close() = try {
delegate.close()
} finally {
cacheManager.close()
}
在我的应用程序中,我创建一个DAOFacade
,如下所示:
import com.mchange.v2.c3p0.ComboPooledDataSource
import org.h2.Driver
import org.jetbrains.exposed.sql.Database
import java.io.File
val dir = File("/build/db")
val pool = ComboPooledDataSource().apply {
driverClass = Driver::class.java.name
jdbcUrl = "jdbc:h2:file:${dir.canonicalFile.absolutePath}"
user = ""
password = ""
}
val DAO: DAOFacade = DAOFacadeCache(DAOFacadeDatabase(Database.connect(pool)), File(dir.parentFile, "ehcache"))
我的想法是跟踪ID
的{{1}}字段中被修改的MyObject
个Set<Int>
中的{{1} }函数将更改保存在DAOFacadeCache
数据库中。
但是,此解决方案的问题是close
在delegate
中的MyObject
可能会在缓存关闭之前从缓存中逐出(可能会丢失更改)>
是否有可能告诉缓存在将对象从内存中逐出之前对对象执行某些操作?