https://kotlinlang.org logo
#ktor
Title
# ktor
j

James

11/04/2023, 4:16 PM
Hello all, I am trying to create some database persistence in my ktor api. I am using exposed as this is what is in the tutorial by jetbrains. I see no examples of implementing exposed for a case like this:
Copy code
@Serializable
data class RecipeDao(
    @SerialName("id") val recipeId: Int,
    @SerialName("title") val recipeName: String,
    @SerialName("calories") val recipeCalories: Int,
    @SerialName("difficulty-rating") val recipeDifficultyRating: Byte,
    @SerialName("meal-type") val recipeMealType: Byte,
    @SerialName("ingredients") val recipeIngredient: List<IngredientDao>
)
I can easily follow the tutorial and up here:
Copy code
interface DaoFacade {
    suspend fun allRecipes(): List<RecipeDao>
    suspend fun addNewRecipe(
        recipeName: String,
        recipeCalories: Int,
        recipeMealType: Byte,
        recipeDifficultyRating: Byte
    ): RecipeDao?
}

class DaoImpl : DaoFacade {

    private fun rowToRecipe(row: ResultRow) = RecipeDao(
        recipeId = row[Recipes.recipeId],
        recipeName = row[Recipes.recipeName],
        recipeCalories = row[Recipes.recipeCalories],
        recipeMealType = row[Recipes.recipeMealType],
        recipeDifficultyRating = row[Recipes.recipeDifficultyRating],
        // how can I pass ingredients?
    )

    override suspend fun allRecipes(): List<RecipeDao> = DatabaseFactory.dbQuery {
        Recipes.selectAll().map(::rowToRecipe)
    }

    override suspend fun addNewRecipe(
        recipeName: String,
        recipeCalories: Int,
        recipeMealType: Byte,
        recipeDifficultyRating: Byte
    ): RecipeDao? = DatabaseFactory.dbQuery {
        val insertStatement = Recipes.insert {
            it[Recipes.recipeName] = recipeName
            it[Recipes.recipeCalories] = recipeCalories
            it[Recipes.recipeMealType] = recipeMealType
            it[Recipes.recipeDifficultyRating] = recipeDifficultyRating
        }
        insertStatement.resultedValues?.singleOrNull()?.let(::rowToRecipe)
    }
}

val dao: DaoFacade = DaoImpl().apply {
    runBlocking {
        if (allRecipes().isEmpty()) {
            addNewRecipe(
                recipeName = "Katsu",
                recipeCalories = 1000,
                recipeMealType = 1,
                recipeDifficultyRating = 1
            )
        }
    }
}
my tables look like this:
Copy code
object Recipes: Table() {
    var recipeId = integer("recipe_id").autoIncrement()
    var recipeName = varchar(name = "recipe_name", 255)
    var recipeCalories = integer("recipe_calories")
    var recipeDifficultyRating = byte("recipe_difficulty_rating")
    var recipeMealType = byte("recipe_meal_type")
    // not sure if this is correct
    var ingredient = reference(name = "ingredient", refColumn = Ingredients.ingredientId)

    override val primaryKey = PrimaryKey(recipeId)
}

object Ingredients: Table() {
    var ingredientId = integer("ingredient_id").autoIncrement()
    var ingredientName = varchar("ingredient_name", 255)

    override val primaryKey = PrimaryKey(ingredientId)

}
Can anybody point me to where I can find an example of this working? Essentially I would like some help on/example code of exposed ebing implemented with an api that has a list of custom objects being displayed as far as I can see on github I see no examples. I would appreciate if someone can point me in the right direction.
a

Aleksei Tirman [JB]

11/06/2023, 9:31 AM
What exact problem do you experience?
j

James

11/06/2023, 12:07 PM
I solved it now