Search code examples
kotlinkotlin-exposed

How to adjust table name in Kotlin Exposed on runtime


We are using database table names which are prefixed with environment names e.g: instead of just 'Cities' we have 'ci_Cities', 'dev_Cities' and 'prod_Cities'.

The problem is that Schema definitions are based on Kotlin objects, which is nice in an usage, but doesn't allow me to simply inject table prefix in e.g. constructor.

So the question is how to implement such a functionality in Kotlin-Exposed?


Solution

  • In the end I have found solution, which seems to be quite elegant. But I think, that some improvements could be done also in Kotlin Exposed, so that in most cases solution is more concise.

    City.kt

    data class City(val id: Int, val name: String, val timestamp: Instant)
    

    Schema.kt

    import org.jetbrains.exposed.sql.ResultRow
    import org.jetbrains.exposed.sql.Table
    import org.jetbrains.exposed.sql.`java-time`.timestamp
    
    class CitiesSchema(environment: String) {
        val cities = CitiesTable(environment)
    }
    
    class CitiesTable(environment: String) : Table(environment + "_Cities") {
        val id = varchar("id", 99)
        val name = varchar("name", 99)
        val timestamp = timestamp("timestamp")
    }
    

    CitiesRepository.kt

    class CitiesRepository(dataSource: DataSource, private val schema: CitiesSchema) {
        private val database = Database.connect(dataSource).defaultFetchSize(10000)
    
        override fun save(city: City): City {
            transaction(database) {
                schema.cities.insert {
                    it[schema.cities.id] = city.id
                    it[schema.cities.name] = city.name
                    it[schema.cities.timestamp] = city.timestamp
                }
            }
            return city
        }
    

    Then in e.g. Spring you can instantiate your schema:

    @Bean
    public CitiesSchema schema(@Value("${spring.application.env}") String environment) {
        return new CitiesSchema(environment);
    }
    

    It would be nice to have in Kotlin Exposed ability to rename tables/columns on runtime. Then it would be possible to access Kotlin objects without additional ceremonies. Such a feature could look like in Jooq: https://www.jooq.org/doc/3.14/manual-single-page/#settings-render-mapping