抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Ktorm 是直接基于纯 JDBC 编写的高效简洁的轻量级 Kotlin ORM 框架,它提供了强类型而且灵活的 SQL DSL 和方便的序列 API,本文讲述如何在Quarkus中使用Ktorm

快速开始

1.引入依赖

1
2
3
4
5
6
7
8
9
10
// quarkus resteasy依赖,建议使用jackson
implementation("io.quarkus:quarkus-resteasy-reactive-jackson")

// ktorm依赖
implementation("org.ktorm:ktorm-core:${ktOrmVersion}")
implementation("org.ktorm:ktorm-support-mysql:${ktOrmVersion}")

// 如不需要连接池可不引入,也可替换为其他连接池如Druid
// https://github.com/brettwooldridge/HikariCP
implementation("com.zaxxer:HikariCP:5.0.1")

2.配置数据源

1
2
3
quarkus.datasource.jdbc.url=jdbc:mysql://127.0.0.1:3306/test
quarkus.datasource.username=root
quarkus.datasource.password=root

3.配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class KtOrmConfiguration {
@ConfigProperty(name = "quarkus.datasource.jdbc.url")
lateinit var url: String

@ConfigProperty(name = "quarkus.datasource.username")
lateinit var username: String

@ConfigProperty(name = "quarkus.datasource.password")
lateinit var password: String

@ApplicationScoped
fun database(): Database {
// 如不需要数据源可直接返回
// return Database.connect(url,"com.mysql.jdbc.Driver",username,password)

val config = HikariConfig()
config.jdbcUrl = url
config.username = username
config.password = password
config.maxLifetime = 120000
return Database.connect(HikariDataSource(config))
}
}

4.创建表结构

1
2
3
4
5
6
7
8
9
object Employees : Table<Nothing>("t_employee") {
val id = int("id").primaryKey()
val name = varchar("name")
val job = varchar("job")
val managerId = int("manager_id")
val hireDate = date("hire_date")
val salary = long("salary")
val departmentId = int("department_id")
}

5.使用

可在任意位置通过 @Inject 注入直接使用

1
2
3
4
5
6
7
8
@Inject
lateinit var database: Database

func test(){
for (row in database.from(Employees).select()) {
println(row[Employees.name])
}
}

实体类与列绑定

1.定义实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 实体类建议采用interface
// 更多信息可查看https://www.ktorm.org/zh-cn/entities-and-column-binding.html
interface User : Entity<User> {
companion object : Entity.Factory<User>()

var id: Long
var avatarUrl: String
var nickName: String
}

object Users : Table<User>("user") {
val id = long("id").primaryKey().bindTo { it.id }
val avatarUrl = varchar("avatar_url").bindTo { it.avatarUrl }
val nickName = varchar("nick_name").bindTo { it.nickName }
}

2.查询

1
2
// 查询出来为List<User>
val userList = database.sequenceOf(Users).toList()

3.序列化

此时如果在接口处返回User类是无法正常序列化的,需要给 jackson 注册ktorm-jackson序列化模块

  • 引入依赖
    1
    implementation("org.ktorm:ktorm-jackson:${ktOrmVersion}")
  • 注册模块
    1
    2
    3
    4
    5
    6
    @Singleton
    class RegisterCustomModuleCustomizer : ObjectMapperCustomizer {
    override fun customize(mapper: ObjectMapper) {
    mapper.registerModule(KtormModule())
    }
    }

通用Service

1.增加BaseService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* Created by vince on Jun 15, 2022.
*/
abstract class BaseService<E : Entity<E>, T : Table<E>>(private val tableObject: T) {
@Inject
protected lateinit var database: Database

/**
* Insert the given entity into the table and return the effected record number.
*/
open fun add(entity: E): Int {
return database.sequenceOf(tableObject).add(entity)
}

/**
* Update properties of the given entity to the table and return the effected record number.
*/
open fun update(entity: E): Int {
return database.sequenceOf(tableObject).update(entity)
}

/**
* Delete records that satisfy the given [predicate].
*/
open fun deleteIf(predicate: (T) -> ColumnDeclaring<Boolean>): Int {
return database.sequenceOf(tableObject).removeIf(predicate)
}

/**
* Return true if all records match the given [predicate].
*/
open fun allMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
return database.sequenceOf(tableObject).all(predicate)
}

/**
* Return true if at least one record match the given [predicate].
*/
open fun anyMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
return database.sequenceOf(tableObject).any(predicate)
}

/**
* Return true if no records match the given [predicate].
*/
open fun noneMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
return database.sequenceOf(tableObject).none(predicate)
}

/**
* Return the number of records in the table.
*/
open fun count(): Int {
return database.sequenceOf(tableObject).count()
}

/**
* Return the number of records matching the given [predicate] in the table.
*/
open fun count(predicate: (T) -> ColumnDeclaring<Boolean>): Int {
return database.sequenceOf(tableObject).count(predicate)
}

/**
* Return an entity object matching the given [predicate].
*/
open fun findOne(predicate: (T) -> ColumnDeclaring<Boolean>): E? {
return database.sequenceOf(tableObject).find(predicate)
}

/**
* Return a list of entities matching the given [predicate].
*/
open fun findList(predicate: (T) -> ColumnDeclaring<Boolean>): List<E> {
return database.sequenceOf(tableObject).filter(predicate).toList()
}

/**
* Return all entities in the table.
*/
open fun findAll(): List<E> {
return database.sequenceOf(tableObject).toList()
}
}

2.编写UserService

User 为例,其他表也添加相应 xxxService 即可

1
2
3
@ApplicationScoped
class UserService : BaseService<User, Users>(Users) {
}

3.使用

1
2
3
4
5
6
7
8
9
10
@Path("/user")
class UserResource {
@Inject
lateinit var userService: UserService

@GET
fun getOne(): User? {
return userService.findOne { Users.id eq 1 }
}
}

评论