当前位置: 首页 > news >正文

[ Spring ] Spring Boot Mybatis++ 2025

文章目录

          • Structure
          • MyBatis++ Controller Abilities
          • Configure Plugins and Repositories
          • Apply Plugins and Add Dependencies
          • MyBatis++ Spring Properties
          • MyBatis++ Application
          • MyBatis++ Beans
          • MyBatis++ Mapper
          • MyBatis++ Query Builder

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 x.spring.hello.controllerimport org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import x.kotlin.commons.serialize.JSON.toJson
import x.kotlin.commons.serialize.JSON.toJsonOrNull
import x.kotlin.commons.string.UUID
import x.spring.hello.model.User
import x.spring.hello.model.UserExample
import x.spring.hello.repository.UserMapper
import x.spring.hello.mybatis.*@RestController
class UserController {@Autowiredprivate lateinit var userMapper: UserMapper@GetMapping("/01")fun selectAll(): String {val userList = userMapper.selectAll()return userList.toJson()}@GetMapping("/02")fun selectByName(): String {val user = userMapper.selectUserByName("Jimmy")return user.toJsonOrNull().orEmpty()}@GetMapping("/03")fun selectByCondition(): String {val condition = condition { it.eq(User::name, "Jimmy") }val users = userMapper.selectList(condition.build())return users.toJson()}@GetMapping("/04")fun insert(): String {val user = User()user.name = UUID.short()userMapper.insert(user)return user.toJson()}@GetMapping("/05")fun insertOrUpdate(): String {val user = User()user.id = "1"user.name = UUID.short()userMapper.insertOrUpdate(user)return user.toJson()}@GetMapping("/06")fun updateByCondition(): String {val cond1 = condition { it.isNotNull(User::id) }val cond2 = condition { it.eq(User::name, "Jimmy") }val cond3 = condition { it.gt(User::age, 15) }val cond4 = condition {it.set(User::name, "Jimmy")it.set(User::age, 18)}val condition = cond1 and cond2 and cond3 attributes cond4val count = userMapper.update(condition.build())return count.toJson()}@GetMapping("/07")fun updateByEntityAndCondition(): String {val entity = User()entity.name = "Updated"entity.age = 36val cond1 = condition { it.isNotNull(User::id) }val cond2 = condition { it.like(User::name, "Jimmy") }val cond3 = condition { it.gt(User::age, 35) }val condition = cond1 and (cond2 or cond3)val count = userMapper.update(entity, condition.build())return count.toJson()}@GetMapping("/08")fun updateByExampleAndCondition(): String {val example = UserExample()example.age = 18val cond1 = condition { it.isNotNull(User::id) }val cond2 = condition { it.like(User::name, "Jimmy") }val cond3 = condition { it.gt(User::age, 35) }val condition = cond1 and (cond2 or cond3) values exampleval count = userMapper.update(condition.build())return count.toJson()}@GetMapping("/09")fun selectCrossTables(): String {val userRoles = userMapper.selectUserRole()return userRoles.toJson()}
}
Configure Plugins and Repositories
pluginManagement {repositories {gradlePluginPortal()google()mavenCentral()}
}dependencyResolutionManagement {repositoriesMode = RepositoriesMode.PREFER_SETTINGSrepositories {gradlePluginPortal()google()mavenCentral()}
}buildscript {repositories {gradlePluginPortal()google()mavenCentral()}
}plugins {id("org.jetbrains.kotlin.jvm") version "2.0.21" apply falseid("org.jetbrains.kotlin.kapt") version "2.0.21" apply falseid("org.jetbrains.kotlin.plugin.spring") version "2.0.21" apply falseid("org.springframework.boot") version "3.4.1" apply false
}include("spring-mybatis")
Apply Plugins and Add Dependencies
plugins {id("org.jetbrains.kotlin.jvm")id("org.jetbrains.kotlin.kapt")id("org.jetbrains.kotlin.plugin.spring")id("org.springframework.boot")
}java {toolchain {languageVersion = JavaLanguageVersion.of(17)}
}dependencies {val springBootVersion = "3.4.1"val springCloudVersion = "4.2.0"val springCloudAlibabaVersion = "2023.0.3.2"// commonsapi("io.github.hellogoogle2000:kotlin-commons:1.0.19")// kotlinapi("org.jetbrains.kotlin:kotlin-reflect:2.0.21")// springapi("org.springframework.boot:spring-boot-starter:$springBootVersion")api("org.springframework.boot:spring-boot-starter-web:$springBootVersion")api("org.springframework.cloud:spring-cloud-starter-bootstrap:$springCloudVersion")// mybatisapi("link.thingscloud:quick-spring-boot-starter-mybatis-plus:2025.01.22")
}
MyBatis++ Spring Properties
# service
server.port=10003
spring.application.name=mybatis
spring.profiles.active=dev
spring.devtools.add-properties=false
# mybatis
spring.datasource.username=root
spring.datasource.password=123456789
spring.datasource.url=jdbc:mysql://localhost:3306/dev?characterEncoding=utf-8&serverTimezone=UTC
MyBatis++ Application
package x.spring.helloimport org.mybatis.spring.annotation.MapperScan
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication@SpringBootApplication
@MapperScan(basePackages = ["x.spring.hello.repository"])
class MybatisApplicationfun main(args: Array<String>) {runApplication<MybatisApplication>(*args)
}
MyBatis++ Beans
package x.spring.hello.modelimport com.baomidou.mybatisplus.annotation.IdType
import com.baomidou.mybatisplus.annotation.TableIdclass User {@TableId(type = IdType.ASSIGN_UUID)var id = ""var name = ""var age = 0
}
package x.spring.hello.modelclass UserExample {var id: String? = nullvar name: String? = nullvar age: Int? = null
}
package x.spring.hello.modelclass UserRoleQueryResult {var name = ""var role = ""
}
MyBatis++ Mapper

mapper sometimes called interface, service or repository in other projects

package x.spring.hello.repositoryimport link.thingscloud.quick.mybatisplus.base.BaseMapper
import org.apache.ibatis.annotations.Select
import x.spring.hello.model.User
import x.spring.hello.model.UserRoleQueryResultinterface 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 user.name as name,role.name as role from user left join roleon user.roleId = role.id""")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 x.spring.hello.mybatisimport com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberPropertiesfun 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::class.java)configurator.configure(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 {configurator.configure(it)it.and { other.configurator.configure(it) }}return QueryCondition(configurator)
}infix fun <T : Any> QueryCondition<T>.or(other: QueryCondition<T>): QueryCondition<T> {val configurator = ConditionConfigurator {configurator.configure(it)it.or { other.configurator.configure(it) }}return QueryCondition(configurator)
}infix fun <T : Any> QueryCondition<T>.not(other: QueryCondition<T>): QueryCondition<T> {val configurator = ConditionConfigurator {configurator.configure(it)it.not { other.configurator.configure(it) }}return QueryCondition(configurator)
}infix fun <T : Any> QueryCondition<T>.attributes(other: QueryCondition<T>): QueryCondition<T> {val configurator = ConditionConfigurator {configurator.configure(it)other.configurator.configure(it)}return QueryCondition(configurator)
}inline infix fun <reified T : Any, reified S : Any> QueryCondition<T>.values(example: S): QueryCondition<T> {val configurator = ConditionConfigurator { wrapper ->configurator.configure(wrapper)val properties = S::class.memberPropertiesproperties.forEach { propertyS ->val value = propertyS.get(example)value.takeIf { it != null } ?: return@forEachval property = T::class.findPropertyByName(propertyS.name)property.takeIf { it != null } ?: return@forEachwrapper.set(property, value)}}return QueryCondition(configurator)
}inline fun <reified T : Any> KClass<T>.findPropertyByName(name: String): KProperty1<T, *>? {return memberProperties.firstOrNull { it.name == name }
}

相关文章:

[ Spring ] Spring Boot Mybatis++ 2025

文章目录 StructureMyBatis Controller AbilitiesConfigure Plugins and RepositoriesApply Plugins and Add DependenciesMyBatis Spring PropertiesMyBatis ApplicationMyBatis BeansMyBatis MapperMyBatis Query Builder Structure this blog introduce 3 ways using mybat…...

JAVAweb学习日记(九) MySQL-事务索引

一、事务-介绍 示例代码&#xff1a; 二、事务-四大特性 三、索引-介绍 无索引&#xff1a;全表扫描&#xff08;对应字段逐一比较&#xff09; 有索引&#xff1a;根据索引结构高效获取数据 优缺点&#xff1a; 四、索引-结构 五、索引-操作语法...

企业加密软件(天锐绿盾)

天锐绿盾是一款功能强大的企业加密软件&#xff0c;以下是对其的详细介绍&#xff1a; 一、产品概述 天锐绿盾&#xff08;又名绿盾信息安全管理软件&#xff09;&#xff0c;专注于企业数据防泄密&#xff0c;致力于为企业提供全方位的数据安全保障。其官网为www.drhchina.c…...

Python实现监督学习与无监督学习

在机器学习中,算法被广泛应用于解决实际问题。监督学习与无监督学习是其中两种重要的学习范式。监督学习通过已标注的数据进行训练,目标是学会预测未知数据的标签。而无监督学习不需要数据的标签,它专注于数据的结构和模式,通常用于聚类或降维等任务。 本教程的目标是帮助…...

Python网络自动化运维---批量登录设备

文章目录 目录 文章目录 前言 实验准备 一.批量登录 IP 连续的设备 1.1.1 实验代码 1.1.2 代码分段分解 1.1.3 实验结果验证 二.批量登录 IP 不连续的设备 2.2.1 实验代码 2.2.2 代码分段分解 2.2.3 实验结果验证 前言 在生产环境中&#xff0c;我们通常需要登录多个设备…...

如何抓取酒店列表: 揭开秘密

搜索酒店列表是一种强大的工具&#xff0c;可以从各种在线资源中收集有关住宿、价格和可用性的综合数据。无论您是要比较价格、分析市场趋势&#xff0c;还是要创建个性化的旅行计划&#xff0c;搜索都能让您有效地汇编所需的信息。在本文中&#xff0c;我们将介绍如何搜索酒店…...

day32-文件共享服务ftp与smb

文件共享服务方案有很多&#xff0c;了解即可 ftp&#xff08;简单文件传输服务&#xff09; 提供用户认证机制 可以输入账号密码 python -m SimpleHTTPServer nginx也提供了文件下载的功能 提供用户认证机制 反向代理&#xff0c;负载均衡 web服务器&#xff0c;静态文件…...

快速傅里叶离散变换FFT (更新中)

声明&#xff1a;参考了 y y c yyc yyc 的 blog 和 PPT (from smwc) &#xff0c;以及 w z r wzr wzr 的 blog 。 目录 Part 1 多项式Part 2 FFT概论Part 3 点值与插值Part 4 复数&#xff0c;单位根Part 5 Part 1 多项式 定义&#xff1a;对于有限数列 A 0 A_{0} A0​~ n…...

【从零开始入门unity游戏开发之——C#篇48】C#补充知识点——静态导入、异常捕获和异常筛选器、nameof运算符

考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...

8.PPT:小李-第二次世界大战【21】

目录 NO123 ​ NO4567 ​ NO8\9\10\11​ 图片→格式→大小对话框→锁定纵横比✔动画→飞入→效果选项&#xff1a;方向/序列→开始→持续时间→延迟时间持续时间&#xff1a;1s延迟&#xff1a;0.5s音频剪切时间&#xff1a;0.5s&#xff1a;00:00.500自动换片时间设置&…...

企业百科和品牌百科创建技巧

很多人比较困惑&#xff0c;创建百科词条需要注意哪些事情&#xff1f;为什么参考提交了权威新闻参考资料还是没有通过&#xff0c;下面小马识途营销顾问就为大家解答疑惑&#xff1a; 1、品牌词以及企业词提交 1&#xff09;如果没有词条&#xff0c;我们可以通过平台提供的急…...

搭建集成开发环境PyCharm

1.下载安装Python&#xff08;建议下载并安装3.9.x&#xff09; https://www.python.org/downloads/windows/ 要注意勾选“Add Python 3.9 to PATH”复选框&#xff0c;表示将Python的路径增加到环境变量中 2.安装集成开发环境Pycharm http://www.jetbrains.com/pycharm/…...

【Rust自学】16.4. 通过Send和Sync trait来扩展并发

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 16.4.1. Send和Sync trait Rust语言本身的并发特性较少&#xff0c;目前所提及的并发特性都来自于标准库&#xff0c;而不是语言本身。其…...

2025年02月05日Github流行趋势

项目名称&#xff1a;OCRmyPDF 项目地址url&#xff1a;https://github.com/ocrmypdf/OCRmyPDF项目语言&#xff1a;Python历史star数&#xff1a;15872今日star数&#xff1a;157项目维护者&#xff1a;jbarlow83, fritz-hh, apps/dependabot, mawi12345, mara004项目简介&…...

拉取本地的 Docker 镜像的三种方法

方法 1&#xff1a;通过 docker save 和 docker load 导出和导入镜像 在本地服务器上导出镜像&#xff1a; 使用 docker save 将镜像保存为一个 .tar 文件&#xff1a; docker save -o mysql-5.7.tar mysql:5.7 将镜像文件传输到其他服务器&#xff1a; 你可以通过 scp 或其他…...

springboot+vue+uniapp的校园二手交易小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…...

NeetCode刷题第21天(2025.2.4)

文章目录 114 Gas Station 加油站115 Hand of Straights 顺子之手116 Merge Triplets to Form Target 将 Triplelet 合并到 Form Target117 Partition Labels 分区标签118 Valid Parenthesis String 有效的括号字符串119 Insert Interval 插入间隔120 Merge Intervals 合并区间…...

人工智能|本地部署|ollama+chatbox快速Windows10下部署(初级篇)

一、 前言&#xff1a; 其实早一个月我已经使用过deepseek&#xff0c;并且也在自己的机器上通过ollama部署过&#xff0c;但一直没有太多动力&#xff0c;现在感觉还是的记录一下&#xff0c;省的自己给忘掉了 本文只是简单记录一下ollamaopen-webuichatbox部署通过网盘分享…...

chrome插件模板;使用 React 18 和 Webpack 5 的 Chrome 扩展样板

一、软件介绍&#xff08;文末提供下载&#xff09; 这是一个基本的 Chrome 扩展样板&#xff0c;可帮助您编写模块化和现代的 Javascript 代码&#xff0c;轻松加载 CSS&#xff0c;并在代码更改时自动重新加载浏览器。 github地址&#xff1a;https://github.com/lxieyang/c…...

大语言模型极速部署:Ollama 与 One-API 完美搭建教程

大语言模型极速部署&#xff1a;Ollama 与 One-API 完美搭建教程 本文将介绍如何通过命令行工具部署 Ollama 和 One-API&#xff0c;帮助你快速搭建私有化大模型。 一、安装 Ollama Ollama 是一个容器化的应用&#xff0c;方便部署和管理 AI 模型。以下是安装 Ollama 的步骤。…...

从电视伴音收音机消亡看数字技术演进与仪器集成化趋势

1. 从一台“电视伴音收音机”说起&#xff1a;一个时代的消逝与技术演进的注脚我书桌抽屉的角落里&#xff0c;一直躺着一台老旧的收音机。它不是普通的AM/FM收音机&#xff0c;在它的波段选择旋钮上&#xff0c;除了熟悉的“AM”和“FM”&#xff0c;还有一个略显神秘的“TV”…...

032随机链表的复制

随机链表的复制 题目链接&#xff1a;https://leetcode.cn/problems/copy-list-with-random-pointer/description/?envTypestudy-plan-v2&envIdtop-100-liked 我的解答&#xff1a; public Node copyRandomList(Node head) {Node dummy new Node(-1);Node curhead, newCu…...

工业视觉检测:从分类到检测的数据多样性策略对比与实战指南

1. 项目概述与核心问题在工业视觉检测领域&#xff0c;我们常常遇到一个令人头疼的“过拟合”现象&#xff1a;模型在实验室里用精心采集的样本训练&#xff0c;准确率能冲到99.9%&#xff0c;可一旦部署到产线上&#xff0c;面对光照变化、产品批次差异、背景干扰甚至相机抖动…...

边缘TTS实战:本地部署高质量语音合成与性能优化指南

1. 项目概述&#xff1a;当TTS遇见边缘计算最近在折腾一个需要实时语音合成的项目&#xff0c;发现了一个挺有意思的仓库&#xff1a;travisvn/openai-edge-tts。这名字一看就很有料&#xff0c;把“OpenAI”和“Edge-TTS”这两个词组合在一起&#xff0c;背后指向的是一个非常…...

CocoaPods终极版本管理指南:掌握语义化版本控制与依赖锁定策略

CocoaPods终极版本管理指南&#xff1a;掌握语义化版本控制与依赖锁定策略 【免费下载链接】CocoaPods The Cocoa Dependency Manager. 项目地址: https://gitcode.com/gh_mirrors/co/CocoaPods CocoaPods是iOS和macOS开发中最受欢迎的依赖管理器&#xff0c;它通过智能…...

AI编程助手文档自动化:dev-docs-skill实现PRD、API与CHANGELOG高效管理

1. 项目概述&#xff1a;一个为AI编程助手“赋能”的文档自动化工具 如果你和我一样&#xff0c;是个在多个项目间穿梭、既要写代码又要维护文档的开发者&#xff0c;那你一定对“文档债”深恶痛绝。代码写完了&#xff0c;功能上线了&#xff0c;但更新API文档、记录变更日志、…...

从亚投行高大幕墙钢架设计谈幕墙结构变形设计

从亚投行高大幕墙钢架设计谈幕墙结构变形设计 【摘 要】   幕墙变形设计是幕墙设计时一个非常重要的考虑要素,它是决定幕墙结构设计质量的关键因素。本文以亚洲基础建设投资银行总部大楼项目南北中厅立面高大幕墙钢架设计为例,从宏观、中观和微观三个维度分析与其连接的主…...

管 Vibe Coding 项目,就像管公共厕所

本文整理自"AI炼金术"播客对徐文浩的访谈&#xff0c;探讨 AI 辅助编程&#xff08;Vibe Coding&#xff09;在组织落地后面临的治理挑战和应对策略。从"屎山三年一遇"到"屎山月月有"传统软件开发中&#xff0c;一个系统的"屎山化"通常…...

在Android Termux中部署轻量级Docker环境:原理、部署与实战指南

1. 项目概述与核心价值最近在折腾移动设备上的开发环境&#xff0c;发现一个挺有意思的项目&#xff1a;George-Seven/Termux-Udocker。简单来说&#xff0c;它是在Android平台的Termux终端模拟器里&#xff0c;实现一个轻量级的、用户空间&#xff08;User-Space&#xff09;的…...

量子信号处理技术及其在离子阱系统中的应用

1. 量子信号处理技术概述量子信号处理&#xff08;Quantum Signal Processing, QSP&#xff09;是近年来量子计算领域涌现的一项基础性技术&#xff0c;它通过精心设计的量子比特旋转序列&#xff0c;实现对量子数据的系统性多项式变换。这项技术的核心价值在于&#xff0c;它为…...