初识Ktorm
Ktorm是什么?
一个基于纯JDBC的轻量级ORM框架
- kotlin
- 强类型
- SqlDSL
- 序列化API 使用
filter
、map
、sortedBy
等序列函数进行查询,就像使用 Kotlin 中的原生集合一样方便 - 无配置文件无xml,没有注解,没有其他第三方依赖
- 易扩展的设计,可以灵活编写扩展,支持更多运算符、数据类型、 SQL 函数、数据库方言等
Install
build.gradle.kts:
1 | implementation("org.ktorm:ktorm-core:3.4.1") |
序列化
除了 JDK 序列化,ktorm-jackson 模块还为你提供了使用 JSON 格式进行序列化的功能。该模块为 Java 中著名的 JSON 框架 Jackson 提供了一个扩展,它支持将 Ktorm 中的实体对象格式化为 JSON,以及从 JSON 中解析实体对象。我们只需要将 KtormModule
注册到 ObjectMapper
中:
1 | val objectMapper = ObjectMapper() |
连接数据库
1 | val database = Database.connect("jdbc:mysql://localhost:3306/你的数据库名称", user = "数据库用户名", password = "密码") |
表、实体类
描述表结构,我试着把原来项目中JPA定义的Entity类转换成Ktorm的表描述:
原先的JPA Entity
1 |
|
先不绑定到Entity,只需Table
的泛型设为Nothing
1 | object AdminUsers: Table<Nothing>("t_admin_user"){ |
ktorm的表定义与实体类定义是分开的,Table
的泛型可以指定绑定到哪个实体类,我们写个实体类,然后想办法把原来JPA Entity上Swagger、Validated相关的注解迁移到新的Ktorm实体:
1 | interface AdminUser: Entity<AdminUser>{ |
可以看到,Ktorm 中的实体类都继承了 Entity<E>
接口,这个接口为实体类注入了一些通用的方法。实体类的属性则使用 var 或 val 关键字直接定义即可,根据需要确定属性的类型及是否为空。有一点可能会违背你的直觉,Ktorm 中的实体类并不是 data class,甚至也不是一个普通的 class,而是 interface。这是 Ktorm 的设计要求,通过将实体类定义为 interface,Ktorm 才能够实现一些特别的功能,以后你会了解到它的意义。
众所周知,接口并不能被实例化,既然实体类被定义为接口,我们要如何才能创建一个实体对象呢?Ktorm 提供了一个 Entity.create
函数,这个函数会使用 JDK 动态代理生成实体类接口的实现,并为我们创建一个实体对象。要创建对象,可以这样写:
1 | val user = Entity.create<AdminUser>() |
因为 Entity.Factory
类重载了 invoke 运算符,所以你可以把这个伴随对象当函数一样直接加上括号进行调用,创建对象的代码变成了这样:
1 | val user = AdminUser() |
但是interface上没法直接加注解,所以得定义自己的实体类(2.5版本之后可以绑定任意实体类)
所以我们想办法把注解加到interface的field上面,既然field没有back-field无法添加注解,那我们试着加在get方法上,@get:注解名称
1 | interface AdminUser: Entity<AdminUser>{ |
这样我们就可吧实体类绑定到表上了,稍微修改了下几个表字段的类型:
1 | object AdminUsers: Table<AdminUser>("t_admin_user"){ |
写个简单的接口验证下:
1 |
|
但是实际上并不行,因为我们这个AdminUser
是一个接口,jackson并不能把他deserialize,我们还是得新建个参数类(所以ktorm版的AdminUser上的@Validated相关接口可以去掉,移到新的参数接口上啦):
参数data class:
1 |
|
接口改一改:
1 |
|
测试下参数校验:
1 | { |
再试着填完参数测试:
1 | { |