Structure
this blog introduce 3 ways using mybatis
- based on annotationed SQL and Query interfaces : suppored by MyBatis framework
- based on Query Wrapper : supported by MyBatis Plus framework
- MyBatis Plus provides a easier way to dynamically set condition and updated fields
- base on Query Condition : combined MyBatis Plus and Kotlin, so called MyBatis++
- MyBatis++ provides a more easier way to build complicated conditions
- and supports update values through an Example bean
MyBatis++ Controller Abilities
this controller present multiple ways to do CURD with MyBatis++
you can choose your favorite ones or those match your current project most comfortably
package import import import import import import import import import import .* @RestController class UserController { @Autowired private lateinit var userMapper: UserMapper @GetMapping("/01") fun selectAll(): String { val userList = () return () } @GetMapping("/02") fun selectByName(): String { val user = ("Jimmy") return ().orEmpty() } @GetMapping("/03") fun selectByCondition(): String { val condition = condition { (User::name, "Jimmy") } val users = (()) return () } @GetMapping("/04") fun insert(): String { val user = User() = () (user) return () } @GetMapping("/05") fun insertOrUpdate(): String { val user = User() = "1" = () (user) return () } @GetMapping("/06") fun updateByCondition(): String { val cond1 = condition { (User::id) } val cond2 = condition { (User::name, "Jimmy") } val cond3 = condition { (User::age, 15) } val cond4 = condition { (User::name, "Jimmy") (User::age, 18) } val condition = cond1 and cond2 and cond3 attributes cond4 val count = (()) return () } @GetMapping("/07") fun updateByEntityAndCondition(): String { val entity = User() = "Updated" = 36 val cond1 = condition { (User::id) } val cond2 = condition { (User::name, "Jimmy") } val cond3 = condition { (User::age, 35) } val condition = cond1 and (cond2 or cond3) val count = (entity, ()) return () } @GetMapping("/08") fun updateByExampleAndCondition(): String { val example = UserExample() = 18 val cond1 = condition { (User::id) } val cond2 = condition { (User::name, "Jimmy") } val cond3 = condition { (User::age, 35) } val condition = cond1 and (cond2 or cond3) values example val count = (()) return () } @GetMapping("/09") fun selectCrossTables(): String { val userRoles = () return () } }
Configure Plugins and Repositories
pluginManagement { repositories { gradlePluginPortal() google() mavenCentral() } } dependencyResolutionManagement { repositoriesMode = RepositoriesMode.PREFER_SETTINGS repositories { gradlePluginPortal() google() mavenCentral() } } buildscript { repositories { gradlePluginPortal() google() mavenCentral() } } plugins { id("") version "2.0.21" apply false id("") version "2.0.21" apply false id("") version "2.0.21" apply false id("") version "3.4.1" apply false } include("spring-mybatis")
Apply Plugins and Add Dependencies
plugins { id("") id("") id("") id("") } java { toolchain { languageVersion = (17) } } dependencies { val springBootVersion = "3.4.1" val springCloudVersion = "4.2.0" val springCloudAlibabaVersion = "2023.0.3.2" // commons api(".hellogoogle2000:kotlin-commons:1.0.19") // kotlin api(":kotlin-reflect:2.0.21") // spring api(":spring-boot-starter:$springBootVersion") api(":spring-boot-starter-web:$springBootVersion") api(":spring-cloud-starter-bootstrap:$springCloudVersion") // mybatis api(":quick-spring-boot-starter-mybatis-plus:2025.01.22") }
MyBatis++ Spring Properties
# service =10003 =mybatis =dev -properties=false # mybatis =root =123456789 =jdbc:mysql://localhost:3306/dev?characterEncoding=utf-8&serverTimezone=UTC
MyBatis++ Application
package import import import @SpringBootApplication @MapperScan(basePackages = [""]) class MybatisApplication fun main(args: Array<String>) { runApplication<MybatisApplication>(*args) }
MyBatis++ Beans
package import import class User { @TableId(type = IdType.ASSIGN_UUID) var id = "" var name = "" var age = 0 }
package class UserExample { var id: String? = null var name: String? = null var age: Int? = null }
package class UserRoleQueryResult { var name = "" var role = "" }
MyBatis++ Mapper
mapper sometimes called interface, service or repository in other projects
package import import import import interface UserMapper : BaseMapper<User> { @Select("select * from user") fun selectAll(): MutableList<User> @Select("select * from user where name = #{name}") fun selectUserByName(name: String): User? @Select( """ select as name, as role from user left join role on = """ ) fun selectUserRole(): List<UserRoleQueryResult> }
MyBatis++ Query Builder
this is the core component to build query condition and examples
difference between entity and example is :
entity will update all field, while example only update non-null fields
package import import import .KProperty1 import fun interface ConditionConfigurator<T : Any> { fun configure(wrapper: KtUpdateWrapper<T>) } data class QueryCondition<T : Any>( val configurator: ConditionConfigurator<T> ) inline fun <reified T : Any> QueryCondition<T>.build(): KtUpdateWrapper<T> { val wrapper = KtUpdateWrapper(T::) (wrapper) return wrapper } inline fun <reified T : Any> condition(configurator: ConditionConfigurator<T>): QueryCondition<T> { return QueryCondition(configurator) } infix fun <T : Any> QueryCondition<T>.and(other: QueryCondition<T>): QueryCondition<T> { val configurator = ConditionConfigurator { (it) { (it) } } return QueryCondition(configurator) } infix fun <T : Any> QueryCondition<T>.or(other: QueryCondition<T>): QueryCondition<T> { val configurator = ConditionConfigurator { (it) { (it) } } return QueryCondition(configurator) } infix fun <T : Any> QueryCondition<T>.not(other: QueryCondition<T>): QueryCondition<T> { val configurator = ConditionConfigurator { (it) { (it) } } return QueryCondition(configurator) } infix fun <T : Any> QueryCondition<T>.attributes(other: QueryCondition<T>): QueryCondition<T> { val configurator = ConditionConfigurator { (it) (it) } return QueryCondition(configurator) } inline infix fun <reified T : Any, reified S : Any> QueryCondition<T>.values(example: S): QueryCondition<T> { val configurator = ConditionConfigurator { wrapper -> (wrapper) val properties = S:: { propertyS -> val value = (example) { it != null } ?: return@forEach val property = T::() { it != null } ?: return@forEach (property, value) } } return QueryCondition(configurator) } inline fun <reified T : Any> KClass<T>.findPropertyByName(name: String): KProperty1<T, *>? { return { == name } }
This is all about this article about Spring Boot Mybatis++ 2025. For more related Spring Boot Mybatis++ 2025, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!