Exposed icon indicating copy to clipboard operation
Exposed copied to clipboard

updateOrInsert Method

Open Im-Fran opened this issue 3 years ago • 2 comments

Hi everyone! I'm currently having some questions about this piece of code created by me:

// Here we assume I have the table 'Users' with the column 'name' and 'city'. And this method is inside my internal user manager.

fun saveUser(user: User) {
    transaction {
        val exists = Users.select { Users.name eq user.name } .count() > 0L
        if (exists) {
            Users.update({ Users.name eq user.name }) {
                it[name] = user.name
                it[city] = user.city
            }
        } else {
            Users.insert {
                it[name] = user.name
                it[city] = user.city
            }
        }
    }
}

Right now I would have no issue with repeating the assignation of the variables, but what will happen with, let's say 64 variables? Do I need to create 128 assignations? I think it would be better a updateOrInsert method that replaces my example so I can just do this:

fun saveUser(user: User) {
    transaction {
        Users.updateOrInsert({ Users.name eq user.name }) {
            it[name] = user.name
            it[city] = user.city
        }
    }
}

I couldn't find something similar in the Wiki or the code, so if someone knows a better way to do this or if it's possible to implement it into Exposed it would be cool ^^

Im-Fran avatar May 11 '22 03:05 Im-Fran

i extracted it with function:

override fun insert(memberDefinition: MemberRepository.MemberDefinition) {
    execInsert {
        insertOrUpdate(it, memberDefinition)
    }
}

override fun update(id: Long, memberDefinition: MemberRepository.MemberDefinition) {
    execUpdate(id = id) {
        insertOrUpdate(it, memberDefinition)
    }
}

private fun MemberEntities.insertOrUpdate(
    it: UpdateBuilder<Number>,
    memberDefinition: MemberRepository.MemberDefinition
) {
    it[email] = memberDefinition.email
    it[password] = memberDefinition.password
    it[displayName] = memberDefinition.displayName
    it[introduce] = memberDefinition.introduce
    it[profileDog] = memberDefinition.profileDog.name
    it[role] = memberDefinition.role.name
    it[status] = memberDefinition.status.name
}

execInsert and execUpdate are custom transaction {} wrapper that i created.

If you want to automate this, i think you can create a class that makes dsl with reflection.

However, I think that exposed is a light-weight DSL/DAO.

I wish this was supported too, but It seems difficult. So I using Spring Framework, and expecting spring-data-exposed to appear and support it 😅

Does anyone else have any good ideas?

heli-os avatar May 19 '22 14:05 heli-os

Your solution seems to be a good one, but yeah, it would be nice if it came with the API :p

Im-Fran avatar May 19 '22 16:05 Im-Fran