-
-
Save hizhengfu/b9d8eb76acca2c8535d6f8f58612f492 to your computer and use it in GitHub Desktop.
Exposed 0.30.2 CrudRepository Proposal
This file contains hidden or 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
abstract class CrudRepository <ID, DOMAIN, TABLE : Table> { | |
abstract val table: TABLE | |
abstract fun toDomain(row: ResultRow): DOMAIN | |
abstract fun toRow(domain: DOMAIN): TABLE.(InsertStatement<Number>) -> Unit | |
abstract fun match(id: ID): SqlExpressionBuilder.() -> Op<Boolean> | |
abstract fun extractId(domain: DOMAIN): ID | |
abstract fun updateRow(domain: DOMAIN): TABLE.(UpdateStatement) -> Unit | |
/** | |
* 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: ID): DOMAIN? = transaction { | |
table.select(where = match(id)).singleOrNull()?.let { toDomain(it) } | |
} | |
/** | |
* Simply retrieves all records. | |
*/ | |
fun getAll(): List<DOMAIN> = transaction { | |
table.selectAll().map { 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 { | |
table.insert(toRow(domain)).let { | |
it.resultedValues?.singleOrNull()?.let { toDomain(it) } | |
} | |
} | |
/** | |
* 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 { | |
table.update(where = match(extractId(domain)), body = updateRow(domain)) | |
.let { | |
if(it == 0) null else get(extractId(domain)) | |
} | |
} | |
/** | |
* 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: ID): ID? = transaction { | |
table.deleteWhere(op = match(id)).let { | |
if(it == 0) null else id | |
} | |
} | |
} | |
// Our Domain Object | |
data class Person( | |
val identityId: UUID, | |
val userName: String, | |
val givenName: String, | |
val familyName: String, | |
val email: String | |
) | |
// Our Table Definition | |
object Persons : Table("persons") { | |
val identityId = varchar("identityId", 36) | |
val userName = varchar("userName", 64) | |
val givenName = varchar("givenName", 64) | |
val familyName = varchar("familyName", 64) | |
val email = varchar("email", 64) | |
override val primaryKey = PrimaryKey(identityId) | |
} | |
// Exemplaratory CrudRepositry for managing Persons :-) | |
object PersonRepository : CrudRepository<UUID, Person, Persons>() { | |
override val table = Persons | |
override fun toDomain(row: ResultRow): Person { | |
return Person( | |
identityId = UUID.fromString(row[Persons.identityId]), | |
userName = row[Persons.userName], | |
givenName = row[Persons.givenName], | |
familyName = row[Persons.familyName], | |
email = row[Persons.email] | |
) | |
} | |
override fun toRow(domain: Person): Persons.(InsertStatement<Number>) -> Unit = { | |
it[identityId] = domain.identityId.toString() | |
it[userName] = domain.userName | |
it[givenName] = domain.givenName | |
it[familyName] = domain.familyName | |
it[email] = domain.email | |
} | |
override fun updateRow(domain: Person): Persons.(UpdateStatement) -> Unit = { | |
it[userName] = domain.userName | |
it[givenName] = domain.givenName | |
it[familyName] = domain.familyName | |
it[email] = domain.email | |
} | |
override fun match(id: UUID): SqlExpressionBuilder.() -> Op<Boolean> = { | |
Persons.identityId eq id.toString() | |
} | |
override fun extractId(domain: Person): UUID = domain.identityId | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is not a complete Repository, but just a Data Mapper.
It doesn't have a cache. Also, it doesn't provide any way to search for records with criteria different from id.
But anyway it looks promising.
Shouldn't
get
call inupdate
be outside of transaction? For example, DB could change some data in triggers on commit.create
looks invalid to me.INSERT
generally doesn't return all column values.create
should probably haveget(extractId(domain))
, the same asupdate
.I've fixed this, and also made various improvements in https://gist.github.com/grv87/2a4969dc1277e43df4d22032919a0026