MyBatis系列三: XxxMapper.xml-SQL映射文件

XxxMapper.xml-SQL映射文件

  • 官方文档
  • 基本介绍
  • 详细说明
    • 基本使用
    • parameterType(输入参数类型)
    • 传入HashMap
    • resultMap(结果集映射)

在这里插入图片描述

官方文档

文档地址: https://mybatis.org/mybatis-3/zh_CN/sqlmap-xml.html

基本介绍

1.MyBatis的真正强大在于它的语句映射(在XxxMapper.xml配置), 由于它的异常强大, 如果拿它跟具有相同功能的JDBC代码进行对比, 你会立即发现省掉了将近95%的代码. MyBatis致力于减少使用成本, 让用户能更专注于SQL代码.

2.SQL映射文件常用的几个顶级元素 (按照应被定义的顺序列出) :

cache - 该命名空间的缓存配置
cache-ref - 引用其它命名空间的缓存配置
resultMap - 描述如何从数据集结果集中加载对象, 是最复杂也是最强大的元素
parameterType - 将会传入这条语句的参数的类全限定名或别名

sql - 可被其它语句引用的可重复的语句块.
insert - 映射插入语句
update - 映射更新语句
delete - 映射删除语句
select - 映射查询语句

详细说明

1.在原来的mybatis项目中, 新建xml-mapper子项目 [参考], 演示xml映射器的使用

2.新建Module后, 先创建需要的包, 再将需要的文件 / 资源拷贝过来(这里我们拷贝Monster.java, resources/jdbc.propertiesmybatis-config.xml)

3.拷贝MonsterMapper.java, MonsterMapper.xmlMonsterMapperTest.java, 做一个比较 干净的讲解环境

基本使用

1.insert, delete, update, select这个我们在前面学习过, 分别对应增删改查的方法和SQL语句的映射
2.如何获取到刚刚添加的Monster对象的id主键 [前面讲解过了]

<insert id="addMonster" parameterType="Monster" useGeneratedKeys="true" keyProperty="id">INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`)VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary})
</insert>

parameterType(输入参数类型)

●parameterType(输入参数类型)
1.传入简单类型, 比如按照idMonster(前面学过)
2.传入POJO类型, 查询时需要有多个筛选条件
3.当有多个条件时, 传入的参数就是Pojo类型的Java对象, 比如这里的Monster对象
4.当传入的参数类是String时, 也可以使用 ${} 来接收参数

●parameterType-应用案例
案例1: 请查询 id = 1 或者 name = 大象精 的妖怪
案例2: 请查询 name 中包含 “牛魔王” 的妖怪

●代码实现
1.修改MonsterMapper.java, 增加方法接口

public interface MonsterMapper {//通过id 或者 名字查询public List<Monster> findMonsterByNameOrId(Monster monster);//查询名字中含有牛魔王的妖怪public List<Monster> findMonsterByName(String name);
}

2.修改MonsterMapper.xml

<mapper namespace="com.zzw.mapper.MonsterMapper"><!--1. 配置/实现public List<Monster> findMonsterByNameOrId(Monster monster);2. 通过id 或者 名字查询3. `id` = #{id} `id`表示表的字段名 #{id}中的id表示你传入的Monster对象的属性名--><select id="findMonsterByNameOrId" parameterType="Monster" resultType="Monster">SELECT * FROM `monster` WHERE `id` = #{id} OR `name` = #{name}</select><!--1. 配置/实现public List<Monster> findMonsterByName(Monster monster);2. 查询名字中 含有 "牛魔王" 的妖怪 - 模糊查询`3. 模糊查询的使用 取值需要 ${value} 取值--><select id="findMonsterByName" parameterType="String" resultType="Monster">SELECT * FROM `monster` WHERE `name` LIKE '%${name}%'</select>
</mapper>

3.修改MonsterMapperTest.java, 进行测试

public class MonsterMapperTest {//属性private SqlSession sqlSession;private MonsterMapper monsterMapper;//编写方法完成初始化@Beforepublic void init() {//获取到sqlSessionsqlSession = MyBatisUtils.getSqlSession();//获取到MonsterMapper对象 monsterMapper=class com.sun.proxy.$Proxy7 代理对象//, 底层是使用了动态代理机制, 后面我们自己实现mybatis底层机制时, 会讲到monsterMapper = sqlSession.getMapper(MonsterMapper.class);System.out.println("monsterMapper=" + monsterMapper.getClass());}@Testpublic void findMonsterByNameOrId(){Monster monster = new Monster();monster.setId(1);monster.setName("大象精");List<Monster> monsters =monsterMapper.findMonsterByNameOrId(monster);for (Monster m : monsters) {System.out.println("m--" + m);}if (sqlSession != null) {sqlSession.close();}System.out.println("查询成功");}@Testpublic void findMonsterByName() {List<Monster> monsters = monsterMapper.findMonsterByName("牛魔王");for (Monster monster : monsters) {System.out.println("monster--" + monster);}if (sqlSession != null) {sqlSession.close();}System.out.println("查询成功");}
}

传入HashMap

●传入HashMap(重点)
1.HashMap传入参数更加灵活, 比如可以灵活地增加查询的属性, 而不受限于Monster这个Pojo属性本身
2.演示如何遍历一个List<Map<String, Object>>的数据类型

●传入HashMap - 应用实例1
要求: 声明一个方法, 按传入参数是HashMap的方式, 查询 id > 10 并且 salary > 40的所有妖怪

1.修改MonsterMapper.java, 增加方法接口

//查询 id > 10 并且 salary > 40的所有妖怪
public List<Monster> findMonsterByIdAndSalary_ParameterHashMap(Map<String, Object> map);

2.修改MonsterMapper.xml

<!--
1. 配置/实现public List<Monster> findMonsterByIdAndSalary_ParameterHashMap(Map<String, Objects> map);
2. 查询 id > 10 并且 salary > 40的所有妖怪
3. 如果是以map形式传入参数, 当你这样写条件 `id` > #{id} 表示你的map 中有一个k-v 中 key为id
-->
<select id="findMonsterByIdAndSalary_ParameterHashMap" parameterType="map" resultType="Monster">SELECT * FROM `monster` WHERE `id` > #{id} AND `salary` > #{salary}
</select>

3.修改MonsterMapperTest.java, 进行测试

@Test
public void findMonsterByIdAndSalary_ParameterHashMap() {Map<String, Object> map = new HashMap<>();map.put("id", 10);map.put("salary", 40);List<Monster> monsters =monsterMapper.findMonsterByIdAndSalary_ParameterHashMap(map);for (Monster monster : monsters) {System.out.println("monster--" + monster);}if (sqlSession != null) {sqlSession.close();}System.out.println("查询成功");
}

●传入和返回HashMap - 应用实例2
要求: 将上面的方法改成返回参数也是HashMap的类型

1.修改MonsterMapper.java, 增加方法接口

//查询 id > 10 并且 salary > 40, 要求传入的参数是HashMap
public List<Map<String, Object>>findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap(Map<String, Object> map);

2.修改MonsterMapper.xml

<!--
1. 配置/实现public List<Map<String, Object>>findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap
2. 查询 id > 10 并且 salary > 40, 要求传入的参数是HashMap
-->
<select id="findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap" parameterType="map"resultType="map">SELECT * FROM `monster` WHERE `id` > #{id} AND `salary` > #{salary}
</select>

3.修改MonsterMapperTest.java, 进行测试

@Test
public void findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap() {Map<String, Object> map = new HashMap<>();map.put("id", 10);map.put("salary", 40);List<Map<String, Object>> maps =monsterMapper.findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap(map);//取出返回的结果-以map的形式取出//回顾java基础, map遍历for (Map<String, Object> monsterMap : maps) {//System.out.println("monsterMap--" + monsterMap);//遍历monsterMap(方式1), 取出属性和对应值//Set<String> keySet = monsterMap.keySet();//for (String key : keySet) {//    Object value = monsterMap.get(key);//    System.out.println(key + "=>" + value);//}//遍历monsterMap(方式2), 取出属性和对应值Set<Map.Entry<String, Object>> entries = monsterMap.entrySet();for(Map.Entry<String, Object> entry : entries) {System.out.println(entry.getKey() + "=>" + entry.getValue());}System.out.println("==================================");}if (sqlSession != null) {sqlSession.close();}System.out.println("查询成功");
}

resultMap(结果集映射)

●基本介绍
当实体类的属性和表的字段不一致时, 我们可以通过resultMap进行映射, 从而屏蔽实体类属性名和表的字段名的不同.

●案例演示
1.创建表user

-- 创建表 user
CREATE TABLE `user` (`user_id` INT NOT NULL AUTO_INCREMENT,`user_email` VARCHAR(255) DEFAULT '',`user_name` VARCHAR(255) DEFAULT '',PRIMARY KEY (`user_id`)
)CHARSET=utf8

2.创建实体类com.zzw.entity.User

public class User {private Integer user_id;private String username;private String useremail;//setter, getter, toString方法
}

3.创建com.zzw.mapper.UserMapper.java

public interface UserMapper {//添加方法public void addUser(User user);//查询所有Userpublic List<User> findAllUser();
}

4.创建com.zzw.mapper.UserMapper.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">
<!--解读1. 这是一个mapper xml 文件2. 该文件可以去实现对应的接口的方法3. namespace 指定该xml文件和哪个接口对应!!!
-->
<mapper namespace="com.zzw.mapper.UserMapper"><!--1. 配置/实现public void addUser(User user);2. 完成添加用户的任务,注意这里--><select id="addUser" parameterType="User">INSERT INTO `user` (`user_email`, `user_name`)VALUES (#{useremail}, #{username})</select><!--1.配置/实现public List<User> findAllUser();2.返回所有User信息3.按照传统的方式完成, 会出现什么问题?=> 如果对象属性和表字段相同时, 就会设置值; 如果不同, 就会是默认值4.我们可以使用resultMap来解决5.resultMap: 表示我们要定义一个resultMap6.id="findAllUserMap" type="User" => id 就是程序员指定的resultMap id, 后面通过id可以使用它7.type="User", 就是你需要返回的对象类型8.result column="user_name" property="username": column="user_name" 表的字段名, property="username" 对象属性名9.resultMap="findAllUserMap" 表示使用我们定义的 resultMap, 通过id关联--><resultMap id="findAllUserMap" type="com.zzw.entity.User"><result column="user_name" property="username"/><result column="user_email" property="useremail"/></resultMap><select id="findAllUser" resultMap="findAllUserMap">SELECT * FROM `user`</select>
</mapper>

5.测试com.zzw.mapper.UserMapperTest

public class UserMapperTest {//属性private SqlSession sqlSession;private UserMapper userMapper;//初始化@Beforepublic void init() {sqlSession = MyBatisUtils.getSqlSession();userMapper = sqlSession.getMapper(UserMapper.class);}@Testpublic void addUser() {User user = new User();user.setUsername("jack");user.setUseremail("jack@163.com");userMapper.addUser(user);//如果是增删改, 需要提交事务if (sqlSession != null) {sqlSession.commit();sqlSession.close();}System.out.println("增加成功");}@Testpublic void findAllUser() {List<User> users = userMapper.findAllUser();for (User user : users) {System.out.println("user--" + user);}if (sqlSession != null) {sqlSession.close();}System.out.println("查询成功");}
}

●注意事项和细节
1.解析表字段和对象属性名不一致, 也支持使用字段别名

<!--使用表字段别名, 来解决表的字段名和对象属性名, 不一致问题, 可以用, 但是我们仍然推荐使用resultMap-->
<select id="findAllUser" resultType="User">SELECT user_id, user_name as username, user_email as useremail FROM `user`
</select>

2.说明: 如果是MyBatis-Plus处理就比较简单, 可以使用 注解TableField 来解决实体字段名和表字段名不一致的问题, 还可以使用@TableName来解决 实体类名和表名不一致的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年06月CCF-GESP编程能力等级认证Python编程一级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有几种?( ) A. 1 B. 2 C…

React@16.x(45)路由v5.x(10)源码(2)- history

目录 1&#xff0c;作用1.1&#xff0c;createBrowserHistory1.2&#xff0c;createHashHistory1.3&#xff0c;createMemoryHistory 2&#xff0c;history 对象的属性2.1&#xff0c;action2.2&#xff0c;push / replace / go / goBack / goForward2.3&#xff0c;location2.…

网络配线架的隐藏功能

网络布线是确保现代信息社会高效运转的关键技术之一。在这一领域&#xff0c;网络配线架扮演着至关重要 的角色。它不仅仅是一个简单的物理连接点&#xff0c;更拥有许多隐藏功能&#xff0c;这些功能极大地提升了网络的 效率、稳定性和可管理性。 1、集中管理 网络配线架提…

【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

经典FC游戏web模拟器--EmulatorJS

简介 EmulatorJS是一个基于JavaScript和Webassembly技术的虚拟环境的实现&#xff0c;可以在网页中运行各种经典FC游戏系统&#xff0c;支持任天堂、世嘉、雅达利等经典红白机。EmulatorJS的诞生使得诸如超级玛丽、坦克大战、魂斗罗等经典FC游戏能够以一种全新的方式回归。本文…

SAP MM模块的ATP检查

前面几篇文章都演示和说明ATP的一些设置和操作&#xff0c;通常情况下ATP的检查PP模块&#xff0c;SD模块用的相对来说是比较多的&#xff0c;但是实际上MM模块也会遵循ATP的可用性的检查规则。 当我们在做311、301等移动类型时&#xff0c;系统会根据相应的可用性检查规则&am…

Linux常用指令汇总

Linux常用指令汇总 Cfilt 功能&#xff1a;解析C程序中被修饰的符号&#xff0c;比如变量与函数名称。 示例&#xff1a; 解析编译器 g 修饰的函数名称。 cfilt -s gnu-v3 _Z5printRKSs print(std::basic_string<char, std::char_traits<char>, std::allocator<…

Django 多对多关系

多对多关系作用 Django 中&#xff0c;多对多关系模型的作用主要是为了表示两个模型之间的多对多关系。具体来说&#xff0c;多对多关系允许一个模型的实例与另一个模型的多个实例相关联&#xff0c;反之亦然。这在很多实际应用场景中非常有用&#xff0c;比如&#xff1a; 博…

【每日一个Git命令: cherry-pick】

git cherry-pick 命令的作用是将指定的提交&#xff08;commit&#xff09;应用到其他分支上。这个命令允许你选择一个或多个已有的提交&#xff0c;并将它们作为新的提交引入到当前分支中。 这个过程不会改变项目的历史记录&#xff0c;因为它实际上是创建了这些提交的副本。…

BMA530 运动传感器

型号简介 BMA530是博世&#xff08;bosch-sensortec&#xff09;的一款运动传感器。时尚简约的可穿戴设备为功能强大的组件提供了很小的空间。具有先进功能集的下一代加速度计是世界上最小的加速度传感器&#xff08;1.2 x 0.8 x 0.55 mm&#xff09;。它专为紧凑型设备而设计&…

24/07/02数据结构(1.1201)算法效率顺序表

数据结构基本内容:1.时间复杂度 空间复杂度2.顺序表链表3.栈 队列4.二叉树5.排序 数据结构是存储,组织数据的方式.指相互之间存在一种或多种特定关系的数据元素的集合 算法是定义良好的计算过程.取一个或一组值为输入并产生一个或一组值为输出. 需要知道虽然选择题有20-30个…

Leetcode1114 交替打印 FooBar及其测试

题目描述 相关标签 相关企业 给你一个类&#xff1a; class FooBar { public void foo() { for (int i 0; i < n; i) { print(“foo”); } } public void bar() { for (int i 0; i < n; i) { print(“bar”); } } } 两个不同的线程将会共用一个 FooBar 实例&#xf…

python自动化运维--DNS处理模块dnspython

1.dnspython介绍 dnspython是Pyhton实现的一个DNS工具包&#xff0c;他几乎支持所有的记录类型&#xff0c;可以用于查询、传输并动态更新ZONE信息&#xff0c;同事支持TSIG&#xff08;事物签名&#xff09;验证消息和EDNS0&#xff08;扩展DNS&#xff09;。在系统管理方面&a…

Linux高并发服务器开发(九)Tcp状态转移和IO多路复用

文章目录 0 包裹函数1 多进程服务器流程代码 2 多线程服务器3 TCP状态转移半关闭心跳包 4 端口复用5 IO多路复用技术高并发服务器 6 select代码总结 7 POLLAPI代码poll相对select的优缺点 8 epoll&#xff08;重点&#xff09;API监听管道代码EPOLL 高并发服务器 9 Epoll的两种…

Iot解决方案开发的体系结构模式和技术

前言 Foreword 计算机技术起源于20世纪40年代&#xff0c;最初专注于数学问题的基本原理&#xff1b;到了60年代和70年代&#xff0c;它以符号系统为中心&#xff0c;该领域首先开始面临复杂性问题&#xff1b;到80年代&#xff0c;随着个人计算的兴起和人机交互的问题&#x…

【进阶篇】Java 项目中对使用递归的理解分享

前言 笔者在最近的项目开发中&#xff0c;遇到了两个父子关系紧密相关的场景&#xff1a;评论树结构、部门树结构。具体的需求如&#xff1a;找出某条评论下的所有子评论id集合&#xff0c;找出某个部门下所有的子部门id集合。 在之前的项目开发经验中&#xff0c;递归使用得是…

centos7安装python3.10

文章目录 1. 安装依赖项2. 下载Python 3.10源码3. 解压源码并进入目录4. 配置安装选项5. 编译并安装Python6. 验证安装7.创建软连接8. 安装pip39. 换源 1. 安装依赖项 sudo yum groupinstall -y "Development Tools" sudo yum install -y openssl-devel bzip2-devel…

Eureka的自扩展之道:服务自动扩展的秘诀

&#x1f31f; Eureka的自扩展之道&#xff1a;服务自动扩展的秘诀 在微服务架构中&#xff0c;服务的自动扩展是实现高可用性和弹性伸缩的关键。Eureka作为Netflix开源的服务发现框架&#xff0c;提供了一套机制来支持服务的自动扩展。本文将详细介绍Eureka如何实现服务的自动…

【LeetCode】十、二分查找法:寻找峰值 + 二维矩阵的搜索

文章目录 1、二分查找法 Binary Search2、leetcode704&#xff1a;二分查找3、leetcode35&#xff1a;搜索插入位置4、leetcode162&#xff1a;寻找峰值5、leetcode74&#xff1a;搜索二维矩阵 1、二分查找法 Binary Search 找一个数&#xff0c;有序的情况下&#xff0c;直接…

第4章:Electron主窗口与子窗口管理

4.1 创建主窗口 主窗口是 Electron 应用启动后显示的第一个窗口&#xff0c;通常用来承载应用的主界面。我们使用 BrowserWindow 类来创建主窗口。 4.1.1 创建主窗口的基础代码 // 引入 Electron 模块和 Node.js 的 path 模块 const { app, BrowserWindow } require(electr…