在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):TouK/krush开源软件地址(OpenSource Url):https://github.com/TouK/krush开源编程语言(OpenSource Language):Kotlin 100.0%开源软件介绍(OpenSource Introduction):KrushKrush is a lightweight persistence layer for Kotlin based on Exposed SQL DSL. It’s similar to Requery and Micronaut-data jdbc, but designed to work idiomatically with Kotlin and immutable data classes. It’s based on a compile-time JPA annotation processor that generates Exposed DSL table and objects mappings for you. This lets you instantly start writing type-safe SQL queries without need to write boilerplate infrastructure code. Rationale
ExampleGiven a simple data class Book(
val id: Long? = null,
val isbn: String,
val title: String,
val author: String,
val publishDate: LocalDate
) we can turn it into Krush entity by adding @Entity
data class Book(
@Id @GeneratedValue
val id: Long? = null,
val isbn: String,
val title: String,
val author: String,
val publishDate: LocalDate
) When we build the project we’ll have val book = Book(
isbn = "1449373321", publishDate = LocalDate.of(2017, Month.APRIL, 11),
title = "Designing Data-Intensive Applications", author = "Martin Kleppmann"
)
// insert method is generated by Krush
val persistedBook = BookTable.insert(book)
assertThat(persistedBook.id).isNotNull() So we have now a val bookId = book.id ?: throw IllegalArgumentException()
// toBook method is generated by Krush
val fetchedBook = BookTable.select { BookTable.id eq bookId }.singleOrNull()?.toBook()
assertThat(fetchedBook).isEqualTo(book)
// toBookList method is generated by Krush
val selectedBooks = (BookTable)
.select { BookTable.author like "Martin K%" }
.toBookList()
assertThat(selectedBooks).containsOnly(persistedBook) InstallationGradle Groovy: repositories {
mavenCentral()
}
apply plugin: 'kotlin-kapt'
dependencies {
api "pl.touk.krush:krush-annotation-processor:$krushVersion"
kapt "pl.touk.krush:krush-annotation-processor:$krushVersion"
api "pl.touk.krush:krush-runtime:$krushVersion"
} Gradle Kotlin: repositories {
mavenCentral()
}
plugins {
kotlin("kapt") version "$kotlinVersion"
}
dependencies {
api("pl.touk.krush:krush-annotation-processor:$krushVersion")
kapt("pl.touk.krush:krush-annotation-processor:$krushVersion")
api("pl.touk.krush:krush-runtime:$krushVersion")
} Maven: <dependencies>
<dependency>
<groupId>pl.touk.krush</groupId>
<artifactId>krush-runtime</artifactId>
<version>${krush.version}</version>
</dependency>
</dependencies>
...
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
...
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>pl.touk.krush</groupId>
<artifactId>krush-annotation-processor</artifactId>
<version>${krush.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
...
</executions>
</plugin> Dependencies
Features
However, Krush is not a full-blown ORM library. This means following JPA features are not supported:
UpdatingGiven following entity: @Entity
data class Reservation(
@Id
val uid: UUID = UUID.randomUUID(),
@Enumerated(EnumType.STRING)
val status: Status = Status.FREE,
val reservedAt: LocalDateTime? = null,
val freedAt: LocalDateTime? = null
) {
fun reserve() = copy(status = Status.RESERVED, reservedAt = LocalDateTime.now())
fun free() = copy(status = Status.FREE, freedAt = LocalDateTime.now())
}
enum class Status { FREE, RESERVED } you can call Exposed val reservation = Reservation().reserve().let(ReservationTable::insert)
val freedReservation = reservation.free()
ReservationTable.update({ ReservationTable.uid eq reservation.uid }) { it.from(freedReservation) }
val updatedReservation = ReservationTable.select({ ReservationTable.uid eq reservation.uid }).singleOrNull()?.toReservation()
assertThat(updatedReservation?.status).isEqualTo(Status.FREE)
assertThat(updatedReservation?.reservedAt).isEqualTo(reservation.reservedAt)
assertThat(updatedReservation?.freedAt).isEqualTo(freedReservation.freedAt) For simple cases you can still use Exposed native update syntax: val freedAt = LocalDateTime.now()
ReservationTable.update({ ReservationTable.uid eq reservation.uid }) {
it[ReservationTable.status] = Status.FREE
it[ReservationTable.freedAt] = freedAt
} Associations@Entity
@Table(name = "articles")
data class Article(
@Id @GeneratedValue
val id: Long? = null,
@Column(name = "title")
val title: String,
@ManyToMany
@JoinTable(name = "article_tags")
val tags: List<Tag> = emptyList()
)
@Entity
@Table(name = "tags")
data class Tag(
@Id @GeneratedValue
val id: Long? = null,
@Column(name = "name")
val name: String
) Persisting val tag1 = Tag(name = "jvm")
val tag2 = Tag(name = "spring")
val tags = listOf(tag1, tag2).map(TagTable::insert)
val article = Article(title = "Spring for dummies", tags = tags)
val persistedArticle = ArticleTable.insert(article) Querying and fetching val (selectedArticle) = (ArticleTable leftJoin ArticleTagsTable leftJoin TagTable)
.select { TagTable.name inList listOf("jvm", "spring") }
.toArticleList()
assertThat(selectedArticle).isEqualTo(persistedArticle) Update logic for associations not implemented (yet!) - you have to manually add/remove records from Example projectsContributorsSpecial thanks to Łukasz Jędrzejewski for original idea of using Exposed in our projects. LicenceKrush is published under Apache License 2.0. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论