Mybatis 动态语言 - mybatis-freemarker
前面我们介绍了Mybatis动态SQL的使用;本篇我们介绍使用mybatis- freemarker动态语言生成动态SQL。
如果您对Mybatis动态SQL不太了解,建议您先进行了解后再阅读本篇,可以参考:
Mybatis 动态SQL – 使用if,where标签动态生成条件语句
Mybatis 动态SQL – 使用if,set标签动态生成更新语句
Mybatis 动态SQL – 使用choose标签动态生成条件语句
Mybatis 动态SQL – 使用choose标签动态生成更新语句
Mybatis 动态SQL – 使用trim标签替代where,set标签
Mybatis 动态SQL - 使用foreach标签查询数据、批量新增、批量修改、删除数据
一、数据准备
这里我们直接使用脚本初始化数据库中的数据
-- 如果数据库不存在则创建数据库
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARSET utf8;
-- 切换数据库
USE demo;
-- 创建用户表
CREATE TABLE IF NOT EXISTS T_TEACHER(ID INT PRIMARY KEY COMMENT '教师编号',TEACHER_NAME VARCHAR(64) NOT NULL COMMENT '教师名称',DEPARTMENT VARCHAR(16) NOT NULL COMMENT '所属部门',BIRTH DATE NOT NULL COMMENT '出生年月',DEGREE VARCHAR(16) NOT NULL COMMENT '学历(ZK:专科, BK:本科, YJS:研究生, BS:博士)'
);
-- 插入用户数据
INSERT INTO T_TEACHER(ID, TEACHER_NAME, DEPARTMENT, BIRTH, DEGREE)
VALUES(1, '张三1', '001', '1990-06-12', 'BK'),(2, '李四1', '002', '1992-05-10', 'BK'),(3, '张三2', '003', '1988-01-15', 'YJS'),(4, '李四2', '001', '1979-03-10', 'BK'),(5, '李四3', '003', '1995-08-16', 'YJS');
创建了一个名称为demo的数据库;并在库里创建了名称为T_TEACHER的教师表并向表中插入了数据
二、环境准备
1、添加依赖
<dependency><groupId>org.mybatis.scripting</groupId><artifactId>mybatis-freemarker</artifactId><version>1.2.4</version>
</dependency>
2、创建实体类
在cn.horse.demo下创建TeacherInfo、TeacherInfoQuery实体类:
TeacherInfo类:
package cn.horse.demo;import java.time.LocalDate;public class TeacherInfo {private Integer id;private String name;private String department;private LocalDate birth;private String degree;public void setId(Integer id) {this.id = id;}public Integer getId() {return id;}public void setName(String name) {this.name = name;}public String getName() {return name;}public void setDepartment(String department) {this.department = department;}public String getDepartment() {return department;}public void setBirth(LocalDate birth) {this.birth = birth;}public LocalDate getBirth() {return birth;}public void setDegree(String degree) {this.degree = degree;}public String getDegree() {return degree;}@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("{ ");stringBuilder.append("id: ");stringBuilder.append(this.id);stringBuilder.append(", ");stringBuilder.append("name: ");stringBuilder.append(this.name);stringBuilder.append(", ");stringBuilder.append("department: ");stringBuilder.append(this.department);stringBuilder.append(", ");stringBuilder.append("birth: ");stringBuilder.append(this.birth);stringBuilder.append(", ");stringBuilder.append("degree: ");stringBuilder.append(this.degree);stringBuilder.append(" }");return stringBuilder.toString();}
}
TeacherInfoQuery类:
package cn.horse.demo;public class TeacherInfoQuery {private String department;private String degree;public void setDepartment(String department) {this.department = department;}public String getDepartment() {return department;}public void setDegree(String degree) {this.degree = degree;}public String getDegree() {return degree;}
}
3、Mapper配置文件
在resources的目录下新建TeacherInfoMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.horse.demo.TeacherInfoMapper"></mapper>
4、动态语言配置
在resources下新建mybatis-config.xml配置文件,配置freemarker默认的脚本语言,并引入TeacherInfoMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="logImpl" value="JDK_LOGGING"/><setting name="defaultScriptingLanguage" value="org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="org.gjt.mm.mysql.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/demo?useUnicode=true&useSSL=false&characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value="horse"/></dataSource></environment></environments><mappers><mapper resource="demo/TeacherInfoMapper.xml" /></mappers>
</configuration>
其中<setting name="defaultScriptingLanguage" value="org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver"/>用于配置freemarker作为默认的动态语言
5、日志配置
在resources的目录下新建logging.properties配置文件
handlers=java.util.logging.ConsoleHandler
.level=INFOcn.horse.demo.TeacherInfoMapper.level=FINER
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tT.%1$tL %4$s %3$s - %5$s%6$s%n
在cn.horse.demo下新建JdkLogConfig类:
JdkLogConfig类:
package cn.horse.demo;import java.io.IOException;
import java.io.InputStream;
import java.util.logging.LogManager;public class JdkLogConfig {public JdkLogConfig() {try {InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("logging.properties");LogManager.getLogManager().readConfiguration(inputStream);} catch (IOException e) {throw new RuntimeException(e);}}
}
6、会话工具类
在cn.horse.demo包下新建SqlSessionUtils工具类
package cn.horse.demo;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.InputStream;
import java.util.Objects;public class SqlSessionUtils {private static final SqlSessionFactory sqlSessionFactory;static {// 读取mybatis配置文件InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");// 根据配置创建SqlSession工厂sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}/*** 开启会话* @return*/public static SqlSession openSession() {return sqlSessionFactory.openSession();}/*** 关闭会话* @param sqlSession*/public static void closeSession(SqlSession sqlSession) {if(Objects.nonNull(sqlSession)) {sqlSession.close();}}
}
7、启动程序配置
package cn.horse.demo;import org.apache.ibatis.session.SqlSession;import java.util.List;public class Main {public static void main(String[] args) {// 引入JDK日志配置System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");}private static void find(String statement, TeacherInfoQuery query) {SqlSession sqlSession = null;try {sqlSession = SqlSessionUtils.openSession();List<TeacherInfo> teacherInfoList = sqlSession.selectList(statement, query);for (TeacherInfo teacherInfo: teacherInfoList) {System.out.println(teacherInfo);}} finally {SqlSessionUtils.closeSession(sqlSession);}}private static void insert(String statement, List<TeacherInfo> teacherInfoList) {SqlSession sqlSession = null;try {sqlSession = SqlSessionUtils.openSession();sqlSession.insert(statement, teacherInfoList);sqlSession.commit();} finally {SqlSessionUtils.closeSession(sqlSession);}}private static void update(String statement, TeacherInfo teacherInfo) {SqlSession sqlSession = null;try {sqlSession = SqlSessionUtils.openSession();sqlSession.update(statement, teacherInfo);sqlSession.commit();} finally {SqlSessionUtils.closeSession(sqlSession);}}private static void delete(String statement, List<Integer> idList) {SqlSession sqlSession = null;try {sqlSession = SqlSessionUtils.openSession();sqlSession.delete(statement, idList);sqlSession.commit();} finally {SqlSessionUtils.closeSession(sqlSession);}}
}
三、查询数据
在TeacherInfoMapper.xml配置文件中新增findByQuery查询语句:
<select id="find" resultType="cn.horse.demo.TeacherInfo">SELECTID,TEACHER_NAME name,DEPARTMENT,BIRTH,DEGREEFROM T_TEACHERWHERE 1 = 1<![CDATA[<#if degree?? && '' != degree>AND DEGREE = <@p name='degree'/></#if><#if department?? && '' != department>AND DEPARTMENT = <@p name='department'/></#if>]]>
</select>
#if类似于<if>标签,第一个标签代表的是degree不为null并且不为空字符串,第二个标签代表的是department不为null并且不为空字符串;
测试:
// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");// 查询学历为本科的教师
TeacherInfoQuery query = new TeacherInfoQuery();
query.setDegree("BK");
find("cn.horse.demo.TeacherInfoMapper.find", query);
执行后的结果如下:

四、批量插入数据
在TeacherInfoMapper.xml配置文件中新增insert插入语句:
<insert id="insert">INSERT INTO T_TEACHER(ID, TEACHER_NAME, DEPARTMENT, BIRTH, DEGREE)VALUES<![CDATA[<#list list as teacherInfo>(<@p value=teacherInfo.id/>,<@p value=teacherInfo.name/>,<@p value=teacherInfo.department/>,<@p value=teacherInfo.birth/>,<@p value=teacherInfo.degree/>)<#if teacherInfo_has_next>,</#if></#list>]]>
</insert>
测试:
// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");List<TeacherInfo> teacherInfoList = new ArrayList<>();
TeacherInfo teacherInfo1 = new TeacherInfo();
teacherInfo1.setId(11);
teacherInfo1.setName("张三11");
teacherInfo1.setDepartment("001");
teacherInfo1.setBirth(LocalDate.of(1988, 5, 20));
teacherInfo1.setDegree("BK");
teacherInfoList.add(teacherInfo1);TeacherInfo teacherInfo2 = new TeacherInfo();
teacherInfo2.setId(12);
teacherInfo2.setName("李四12");
teacherInfo2.setDepartment("003");
teacherInfo2.setBirth(LocalDate.of(1989, 8, 10));
teacherInfo2.setDegree("ZK");
teacherInfoList.add(teacherInfo2);
insert("cn.horse.demo.TeacherInfoMapper.insert", teacherInfoList);
执行的结果如下:
![]()
五、更新数据
在TeacherInfoMapper.xml配置文件中新增update更新语句:
<update id="update">UPDATE T_TEACHERSET<![CDATA[ID = <@p name='id'/><#if name?? && '' != name>, TEACHER_NAME = <@p name='name'/></#if><#if department?? && '' != department>, DEPARTMENT = <@p name='department'/></#if><#if birth??>, BIRTH = <@p name='birth'/></#if><#if degree?? && '' != degree>, DEGREE = <@p name='degree'/></#if>]]>WHERE ID = <![CDATA[ <@p name='id'/> ]]>
</update>
测试:
// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");TeacherInfo teacherInfo = new TeacherInfo();
teacherInfo.setId(11);
teacherInfo.setName("张三22");
update("cn.horse.demo.TeacherInfoMapper.update", teacherInfo);
执行的结果如下:
![]()
六、批量删除数据
在TeacherInfoMapper.xml配置文件中新增delete删除语句:
<delete id="delete">DELETE FROM T_TEACHERWHERE ID IN (<![CDATA[<#list list as id><@p value=id/><#if id_has_next>,</#if></#list>]]>)
</delete>
测试:
// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");delete("cn.horse.demo.TeacherInfoMapper.delete", Arrays.asList(11, 12));
执行的结果如下:

相关文章:
Mybatis 动态语言 - mybatis-freemarker
前面我们介绍了Mybatis动态SQL的使用;本篇我们介绍使用mybatis- freemarker动态语言生成动态SQL。 如果您对Mybatis动态SQL不太了解,建议您先进行了解后再阅读本篇,可以参考: Mybatis 动态SQL – 使用if,where标签动态生成条件语…...
软件源码开发,网络中的“摄像头”:运维监控系统
在日常生活中,我们不管是在大街小巷,还是在商场大厦都可以见到一个圆形或是方形带有镜片的“小盒子”,这个“小盒子”就是摄像头,摄像头作为一个能实时录制记录它能照到范围内的视频图像的工具,可以在丢失物品、抓捕坏…...
ping命令
打开运行窗口 首先,我们需要打开运行窗口,可以通过按下WinR组合键打开。然后,在窗口中输入cmd,进入dos命令。 在命令行中输入ping命令 在dos命令行中,我们可以通过输入ping命令来检测网络连接。例如,我们…...
MFC:程序的托盘显示
介绍 关键技术,API函数Shell_NotifyIcon,具体查看msdn吧 实现的主要代码 #define MY_TRAY_ICON_ID (1)/ //其他代码:略BEGIN_MESSAGE_MAP(CTestShowTrayDlg, CDialogEx)//...ON_MESSAGE(WM_MY_TRAY_ICON, &CTestShowTrayDlg::OnMessag…...
AI绘画:StableDiffusion实操教程-斗破苍穹-云韵-婚服(附高清图下载)
大家好,我是小梦,最近一直研究AI绘画。 不久前,我与大家分享了StableDiffusion的全面教程:“AI绘画:Stable Diffusion 终极宝典:从入门到精通 ” 然而,仍有些读者提出,虽然他们已经…...
JS装饰器的介绍
装饰器的基本介绍 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性或参数上。 装饰器使用expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的…...
微信小程序(原生)使用Swiper实现(商品详情)视频和图片轮播(仿京东/淘宝商品详情头部视频+图片轮播)
一、需求 1、如果第一是视频,不进行自动轮播 2、可以手动滑动切换 3、点击播放视频,也可以手动滑动切换 4、视频播放完后,自动轮播 5、视频可以点击暂停和全屏播放二、最终效果 三、源码 播放icon使用了TDesign组件库 1、wxml <swiper c…...
关于for in 循环会遍历原型链上的属性的问题
关于for in 循环会遍历原型链上的属性的问题 for in可遍历原型链上扩展的属性,Object.keys() 只遍历自身属性 1.使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问: Object.prototype.say"cgl"; // 修改Object.p…...
冠达管理:人民币升值板块个股?
人民币增值是当前热门的论题之一。面对这一趋势,许多投资者开端重视人民币增值板块个股的投资时机。可是,终究哪些职业和个股能够从人民币增值中获益?下面从多个视点分析这个问题。 一、出口相关职业 跟着人民币增值,我国的出口企…...
27.EI文章复现《高比例清洁能源接入下计及需求响应的配电网重构》
下载地址:高比例清洁能源接入下计及需求响应的配电网重构 1主要内容 该程序复现《高比例清洁能源接入下计及需求响应的配电网重构》,以考虑网损成本、弃风弃光成本和开关操作惩罚成本的综合成本最小为目标,针对配电网重构模型的非凸性&…...
mysql的索引结构
索引概述 索引( index )是帮助 MySQL 高效获取数据的数据结构 ( 有序 ) 。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些…...
SMT生产中基板的机械清洁处理法有哪些
在S MT贴片加工 过程中,锡育和助焊剂会产生残留物质,残留物中包含有有机酸和可分解的电离子,某中有机酸狊 有腐蚀作用,电高子难留在焊盘还会引(起短路,而且这些残留物在PCBA板上是非常脏的,而旦不符合顾客…...
微服务面试题
一、什么是微服务 二、微服务之间是如何通讯的? 2.1、同步 优点:实时性 缺点:降低了可用性,因为客户端和服务端在请求过程中必须都是可用的 2.1.1、REST 优点:开发成本低,适应异构语言 2.1.2、RPC …...
LeetCode 1132.申请的报告2
数据准备 Create table If Not Exists Actions (user_id int, post_id int, action_date date, action ENUM(view, like, reaction, comment, report, share), extra varchar(10)); create table if not exists Removals (post_id int, remove_date date); Truncate table Act…...
室内探索无人机,解决复杂环境下的任务挑战!
前言 室内探索无人机是一种专为在室内环境中进行任务的无人机系统。相比传统的人员部署,室内探索无人机具有更高的灵活性和机动性,能够在复杂的室内环境中执行任务,用于未知环境的探索和特定目标的搜索。 为完成无人机室内搜索与识别等复杂…...
操作指南 | 如何参与Moonbeam投票委托
投票委托允许没有时间或者专业度一般的用户能够在治理中拥有话语权。该功能加强了决策流程,并且确保更大范围地代表社区利益。 通过Moonbeam委托平台,你需要 $GLMR 和一个相兼容的钱包。此教程使用MetaMask示范。 如何参与投票委托 前往http://delega…...
xxl-job中多节点分片的时候如何在linux服务器开启多个执行器实例?
在 xxl-job 中,可以通过在 Linux 服务器上启动多个执行器实例来实现分布式的分片任务处理。以下是在 Linux 服务器上开启多个执行器实例的步骤: 1.复制并配置多个执行器项目模块: 复制原始的执行器项目模块,并重命名为不同的名称…...
springboot三种注入方式
在Spring Boot中,您可以使用三种主要的方式来进行依赖注入: 构造函数注入(Constructor Injection):您可以在类的构造函数中声明依赖项,然后Spring容器会在创建Bean实例时自动注入这些依赖项。这种方式通常用…...
信息化发展38
组织模型一信息系统战略 1 、信息系统战略是组织用来提供信息服务的计划。 2 、信息系统支撑组织实施其业务战略。业务战略是关于竞争(服务对象想要什么, 竞争做什么) , 定位(组织想以什么方式竞争)和能力…...
PMP含金量再升级!北京上海等地可评职称!
最近PMP证书又“升级”了,不过不是证书上的改变,而是含金量在原有基础上又上升了一个档次。 9月4日,北京市人力资源和社会保障局联合北京市人才工作局发布关于印发《北京市境外职业资格认可目录(3.0版)》的通知,PMP项目管理证书也…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
