Forked from paulschuetz/CrudRepositoryProposal.kt
Last active
December 9, 2021 01:05
-
-
Save grv87/2a4969dc1277e43df4d22032919a0026 to your computer and use it in GitHub Desktop.
Exposed 0.30.2 CrudRepository Proposal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.UUID | |
import org.jetbrains.exposed.dao.id.IdTable | |
import org.jetbrains.exposed.sql.Op | |
import org.jetbrains.exposed.sql.ResultRow | |
import org.jetbrains.exposed.sql.SqlExpressionBuilder | |
import org.jetbrains.exposed.sql.deleteWhere | |
import org.jetbrains.exposed.sql.insert | |
import org.jetbrains.exposed.sql.select | |
import org.jetbrains.exposed.sql.selectAll | |
import org.jetbrains.exposed.sql.statements.UpdateBuilder | |
import org.jetbrains.exposed.sql.transactions.transaction | |
import org.jetbrains.exposed.sql.update | |
interface Entity<ID> { | |
val id: ID | |
} | |
abstract class CrudRepository <DOMAIN_ID, DOMAIN : Entity<DOMAIN_ID>, DB_ID : Comparable<DB_ID>, TABLE : IdTable<DB_ID>> { | |
abstract val table: TABLE | |
abstract fun TABLE.toDomain(row: ResultRow): DOMAIN | |
abstract fun toRow(domain: DOMAIN): TABLE.(UpdateBuilder<Int>) -> Unit | |
abstract fun idToDb(id: DOMAIN_ID): DB_ID | |
abstract fun idFromDb(id: DB_ID): DOMAIN_ID | |
private fun match(id: DOMAIN_ID): SqlExpressionBuilder.() -> Op<Boolean> = { | |
table.id eq idToDb(id) | |
} | |
/** | |
* Get a particular record by its ID. | |
* | |
* @param id The ID of the record to retrieve. | |
* @return The domain object which corresponds to the specified ID if operation was successful or null otherwise. | |
*/ | |
fun get(id: DOMAIN_ID): DOMAIN? = transaction { | |
table.select(where = match(id)).singleOrNull()?.let { table.toDomain(it) } | |
} | |
/** | |
* Simply retrieves all records. | |
*/ | |
fun getAll(): List<DOMAIN> = transaction { | |
table.selectAll().map { table.toDomain(it) } | |
} | |
/** | |
* Creates a new record. | |
* | |
* @param domain The object to be created in its domain form. | |
* @return The newly created record if operation was successful or null otherwise. | |
*/ | |
fun create(domain: DOMAIN): DOMAIN? = transaction { | |
val id = domain.id | |
table.insert { | |
toRow(domain) | |
it[table.id] = idToDb(id) | |
} | |
get(id) | |
} | |
/** | |
* Updates an existing record. | |
* | |
* @param domain The domain object which will be updated. | |
* @return The freshly updated domain object if operation was successful or null otherwise. | |
*/ | |
fun update(domain: DOMAIN): DOMAIN? = transaction { | |
val id = domain.id | |
table.update(where = match(id), body = toRow(domain)) | |
.let { | |
if(it == 0) null else get(id) | |
} | |
} | |
/** | |
* Deletes the single record which corresponds to the specified ID. | |
* | |
* @param id The ID of the record to be deleted. | |
* @return The ID of the deleted record if operation was successful or null otherwise. | |
*/ | |
fun delete(id: DOMAIN_ID): DOMAIN_ID? = transaction { | |
table.deleteWhere(op = match(id)).let { | |
if(it == 0) null else id | |
} | |
} | |
} | |
// Our Domain Object | |
data class Person( | |
override val id: UUID, | |
val userName: String, | |
val givenName: String, | |
val familyName: String, | |
val email: String | |
) : Entity<UUID> | |
// Our Table Definition | |
object Persons : IdTable<String>("persons") { | |
override val id = varchar("identityId", 36).entityId() | |
val userName = varchar("userName", 64) | |
val givenName = varchar("givenName", 64) | |
val familyName = varchar("familyName", 64) | |
val email = varchar("email", 64) | |
override val primaryKey = PrimaryKey(id) | |
} | |
// Exemplaratory CrudRepository for managing Persons :-) | |
object PersonRepository : CrudRepository<UUID, Person, String, Persons>() { | |
override val table = Persons | |
override fun Persons.toDomain(row: ResultRow): Person { | |
return Person( | |
idFromDb(row[id].value), | |
row[userName], | |
row[givenName], | |
row[familyName], | |
row[email] | |
) | |
} | |
override fun toRow(domain: Person): Persons.(UpdateBuilder<Int>) -> Unit = { | |
it[userName] = domain.userName | |
it[givenName] = domain.givenName | |
it[familyName] = domain.familyName | |
it[email] = domain.email | |
} | |
override fun idToDb(id: UUID): String = id.toString() | |
override fun idFromDb(id: String): UUID = UUID.fromString(id) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment