You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello! In our project we are using UUID for almost all entities. We would like to save and retrieve them directly from Exposed, with compilator support (strongly typed). Our "UUID" classes are shared between backend, iOS, Android and JS, so we have to keep them "clean" in only common code
Expectations
We would like to set some kind of annotation / parameter to column, that would allow us to create mapping between Type(binary uuid) stored in Database and Type used in application (some kind of class)
Below I will provide my custom resolution of this issue. Please let me know if it is correct approach, or should I use some other functionality of Exposed.
Prototype
I had no idea where to start, because I could not find any information about column mapping. I created custom column, that internally uses UUIDColumnType:
class TypedUUIDColumnType<T : UUIDType>(private val factory: UUIDTypeFactory<T>) : ColumnType() {
private val uuidColumnType = UUIDColumnType()
override fun sqlType(): String = uuidColumnType.sqlType()
override fun valueFromDB(value: Any): T {
val uuid = uuidColumnType.valueFromDB(value)
val stringRepresentation = uuid.toString()
return factory.createFrom(stringRepresentation)
}
override fun notNullValueToDB(value: Any): Any {
return when (value) {
is String -> uuidColumnType.notNullValueToDB(UUID.fromString(value))
else -> {
val asString = (value as T).asString()
uuidColumnType.notNullValueToDB(UUID.fromString(asString))
}
}
}
override fun nonNullValueToString(value: Any): String {
return (value as T).asString()
}
override fun readObject(rs: ResultSet, index: Int): Any? {
return uuidColumnType.readObject(rs, index)
}
}
fun <T : UUIDType> Table.typedUUID(name: String, factory: UUIDTypeFactory<T>): Column<T> =
registerColumn(name, TypedUUIDColumnType(factory))
Factory itself is simple functional interface, to make sure that all our custom UUID Types can be created from plain string
fun interface UUIDTypeFactory<T : UUIDType> {
fun createFrom(stringId: String): T
}
Abstract UUID Type just implements Comparable interface and hides rawValue of String:
abstract class UUIDType() : Comparable<UUIDType> {
protected abstract val rawValue: String
fun asString() = rawValue
override fun toString(): String = rawValue
override fun compareTo(other: UUIDType): Int {
return rawValue.compareTo(other.rawValue)
}
}
Usage
data class SomeId(override val rawValue: String) : UUIDType() {
companion object : UUIDTypeFactory<SomeId> {
override fun createFrom(stringId: String) = SomeId(stringId)
}
}
object SomeTable : Table() {
val uuid = typedUUID("uuid", SomeId)
}
fun example(newId: SomeId) {
SomeTable.insert {
it[uuid] = newId
}
}
fun retrieveExample():SomeId{
return SomeTable
.selectAll()
.first()
.run { this[SomeTable.uuid] }
}
Conclusion
Usage is pretty convenient, but I'm not sure if I could run in some issues with other DBs or should I be worry about efficiency of this solution
The text was updated successfully, but these errors were encountered:
Background and issue to resolve:
Hello! In our project we are using UUID for almost all entities. We would like to save and retrieve them directly from Exposed, with compilator support (strongly typed). Our "UUID" classes are shared between backend, iOS, Android and JS, so we have to keep them "clean" in only common code
Expectations
We would like to set some kind of annotation / parameter to column, that would allow us to create mapping between Type(binary uuid) stored in Database and Type used in application (some kind of class)
Below I will provide my custom resolution of this issue. Please let me know if it is correct approach, or should I use some other functionality of Exposed.
Prototype
I had no idea where to start, because I could not find any information about column mapping. I created custom column, that internally uses UUIDColumnType:
Factory itself is simple functional interface, to make sure that all our custom UUID Types can be created from plain string
Abstract UUID Type just implements Comparable interface and hides rawValue of String:
Usage
Conclusion
Usage is pretty convenient, but I'm not sure if I could run in some issues with other DBs or should I be worry about efficiency of this solution
The text was updated successfully, but these errors were encountered: