Quick Start
This chapter will guide you on how to get started with Kronos quickly, you can find some sample projects here。
Prepare the project
Add the ORM runtime, the Kronos compiler plugin, the JDBC wrapper, and the database driver used by this example.
build.gradle.kts
plugins {
kotlin("jvm") version "2.4.21"
id("com.kotlinorm.kronos-gradle-plugin") version "0.4.0"
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xcollection-literals", "-Xcontext-sensitive-resolution")
}
}
dependencies {
implementation("com.kotlinorm:kronos-core:0.4.0")
implementation("com.kotlinorm:kronos-jdbc-wrapper:0.4.0")
implementation("org.apache.commons:commons-dbcp2:<latest-stable>")
implementation("com.mysql:mysql-connector-j:<latest-stable>")
}Use a MySQL database named kronos for the following snippets. Replace <latest-stable> with driver and pool versions that match your JDK and database server.
The compiler plugin is part of the runnable setup. It generates
KPojometadata, dynamic members, and query projection types. The full setup is documented in📚Compiler Plugins.
Configure the wrapper
Create one wrapper and set it on Kronos.dataSource before running ORM operations. This example keeps the wrapper at file scope so the same instance is available to DDL and CRUD code.
Db.kt
import com.kotlinorm.Kronos
import com.kotlinorm.wrappers.KronosJdbcWrapper
import com.kotlinorm.beans.config.KronosCommonStrategy
import com.kotlinorm.beans.dsl.Field
import org.apache.commons.dbcp2.BasicDataSource
val wrapper by lazy {
KronosJdbcWrapper(
BasicDataSource().apply {
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/kronos?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC"
username = "user"
password = "******"
}
)
}
fun configureKronos() {
with(Kronos) {
dataSource = { wrapper }
tableNamingStrategy = lineHumpNamingStrategy
fieldNamingStrategy = lineHumpNamingStrategy
defaultDateFormat = "yyyy-MM-dd HH:mm:ss"
createTimeStrategy = KronosCommonStrategy(enabled = true, field = Field("create_time", "createTime"))
updateTimeStrategy = KronosCommonStrategy(enabled = true, field = Field("update_time", "updateTime"))
logicDeleteStrategy = KronosCommonStrategy(enabled = true, field = Field("deleted"))
optimisticLockStrategy = KronosCommonStrategy(enabled = true, field = Field("version"))
}
}For custom wrappers and database detection, see 📚Connect to DB and 📚Custom Wrapper.
Define KPojo classes
Create Kotlin data classes, implement KPojo, and add annotations for table names, keys, indexes, and common fields.
Director.kt
import com.kotlinorm.annotations.CreateTime
import com.kotlinorm.annotations.Default
import com.kotlinorm.annotations.LogicDelete
import com.kotlinorm.annotations.PrimaryKey
import com.kotlinorm.annotations.UpdateTime
import com.kotlinorm.annotations.Version
import com.kotlinorm.interfaces.KPojo
import java.time.LocalDateTime
data class Director(
@PrimaryKey(identity = true)
var id: Int? = null,
var name: String? = null,
@CreateTime
var createTime: LocalDateTime? = null,
@UpdateTime
var updateTime: LocalDateTime? = null,
@LogicDelete
@Default("0") // @Default("false") for Postgres
var deleted: Boolean? = false,
@Version
var version: Int? = 0
) : KPojoMovie.kt
import com.kotlinorm.annotations.Cascade
import com.kotlinorm.annotations.Column
import com.kotlinorm.annotations.CreateTime
import com.kotlinorm.annotations.Default
import com.kotlinorm.annotations.LogicDelete
import com.kotlinorm.annotations.PrimaryKey
import com.kotlinorm.annotations.Table
import com.kotlinorm.annotations.TableIndex
import com.kotlinorm.annotations.UpdateTime
import com.kotlinorm.interfaces.KPojo
import java.time.LocalDateTime
@Table("tb_movie")
@TableIndex("idx_movie_director", ["name", "director_id"], "UNIQUE", "BTREE")
data class Movie(
@PrimaryKey(identity = true)
var id: Int? = null,
@Column("name")
var name: String? = null,
var directorId: Int? = null,
@Cascade(["directorId"], ["id"])
var director: Director? = null,
@CreateTime
var createTime: LocalDateTime? = null,
@UpdateTime
var updateTime: LocalDateTime? = null,
@LogicDelete
@Default("0") // @Default("false") for Postgres
var deleted: Boolean? = false
) : KPojoMapping rules are covered in 📚KPojo, 📚Annotations, and 📚Indexes.
Run the first flow
Call configureKronos(), create the tables, insert a director, and read it back with query-by-example.
Main.kt
import com.kotlinorm.orm.insert.insert
import com.kotlinorm.orm.select.select
fun main() {
configureKronos()
wrapper.table.createTable(Director())
wrapper.table.createTable(Movie())
val result = Director(name = "Kronos")
.insert()
.execute()
val affectedRows = result.affectedRows
val director = Director(name = "Kronos")
.select()
.where()
.first()
}The insert and select generate SQL like this for MySQL.
MySQL
INSERT INTO `director` (`name`, `create_time`, `update_time`, `deleted`, `version`)
VALUES (:name, :createTime, :updateTime, :deleted, :version)
SELECT `id`, `name`, `create_time` AS `createTime`, `update_time` AS `updateTime`, `deleted`, `version`
FROM `director`
WHERE `director`.`name` = :name
AND `deleted` = 0Use 📚Table Operations for DDL, 📚Insert for writes, 📚Conditions for where() behavior, and 📚Troubleshooting when build or runtime behavior differs from this flow.