初识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 | { |