【MyBatis】一天之内快速掌握MyBatis的增删改查

2023-11-12

MyBatis

文章介绍:

一共不到8000字,一天之内可以快速学会mybatis的增删改查,
以及经常使用的操作,不讲废话,只将眼光聚焦到实操上,也可以搭配黑马的视频观看
看完之后,可以自己找个mybatis源码课继续学习
,但是一般的业务代码也只用到文章大部分内容

Mybatis是一款半ORM的持久层框架,简化JDBC的框架

一、快速入门


  1. 创建SQL表
  2. 编写MyBatis配置文件
  3. 编写SQL语句
  4. java定义POJO类
  5. SqlSessionFactory对象,获取SqlSession
  6. 执行Sql语句
  7. 释放资源

二、mapper代理开发


MyBtais使用mapper代理开发三个步骤:

  1. 定义mapper接口方法
  2. 定义SQL语句,其实就是写mapper.xml
  3. 调用者生成mapper 实例化对象,来进行操作
  • 主要记得mapper接口要和resources目录下的mapper.xml一个目录;

  • 如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为

<mappers>
    <!--加载sql映射文件-->
    <!-- <mapper resource="com/itheima/mapper/UserMapper.xml"/>-->
    <!--Mapper代理方式-->
    <package name="com.it.mapper"/>
</mappers>
  • 重复性高的sql语句,在mapper.xml中,使用sql标签,定义sql片段。

三、难点业务


难点1:遇到数据库表字段与实体类属性名名称不一致,如何处理


1. SQL字段起别名

使用sql标签定义statement片段,将数据库字段as成实体类属性名。在statement中include进来。
例如

<sql id="brand_column">
	id, brand_name as brandName, company_name as companyName, ordered, description, status
</sql>
<select id="selectAll" resultType="brand">
    select
    <include refid="brand_column" />
    from tb_brand;
</select>
2. ResultMap 封装结果集,实现数据库字段和实体类属性的映射关系

实现多字段数据库表只有些许字段需要对应修改,完成不一致的属性名和列名的映射

例如

<resultMap id="brandResultMap" type="brand">
     <!--
            id:完成主键字段的映射
                column:表的列名
                property:实体类的属性名
            result:完成一般字段的映射
                column:表的列名
                property:实体类的属性名
        -->
     <result column="brand_name" property="brandName"/>
     <result column="company_name" property="companyName"/>
</resultMap>

<select id="selectAll" resultMap="brandResultMap">
    select *
    from tb_brand;
</select>

难点2: where条件如何添加参数


1. sql语句参数占位符使用
  1. #{}:推荐使用,在sql语句中是 ?存在,就是jdbc的PreparedStatement
  2. ${}:拼接sql语句,存在sql注入问题,底层就是Statement
  3. 使用时机:参数传递用#{};对于可变列名、表名用${},但是实际中没什么用
2.parameterType使用

parameterType,对于有参数的mapper接口,一般在xml中可以省略,框架会自动封装。
例子

/*
* id:唯一标识符
* parameterType:传递参数类型
* resultMap:返回类型
*/
<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id = ${id};
</select>
3.SQL语句中特殊字段处理
  1. 使用xml的转义字符:例如&lt; 就是 < 的转义字符。
  2. <![CDATA[内容]]>,内容里面就写有歧义的内容
4. 总结例子
/*
* id:唯一标识符
* parameterType:传递参数类型,可以省略
* resultMap:返回类型
*/
<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id 
    <![CDATA[
    		<
    ]]>
     #{id};
</select>

难点3: 多条件查询


1. 重点:
条件需要模糊查询
2. mapper接口参数接受
  1. 散装参数接受

    使用 @Param("参数名称") 注解标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位,两个名称要一致。
    代码:

List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);

  1. 实体类封装参数
    保证SQL语句的占位参数名称#{参数名称}跟实体类属性名一致就行了
List<Brand> selectByCondition(Brand brand);
  1. map封装参数
    保证map集合的key跟sql的占位参数名称#{参数名称}一致就行了
List<Brand> selectByCondition(Map map);
3.sql语句编写
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where status = #{status}
    and company_name like #{companyName}
    and brand_name like #{brandName}
</select>

记得占位参数名称#{"参数名称"}与三种方式要对应上。

4.调用

在调用中,要实现模糊查询,应该在调用时封装参数

// 处理参数
    companyName = "%" + companyName + "%";
    brandName = "%" + brandName + "%";

难点4: 添加数据


1.接口方法

参数使用实体类对象

void add(Object obj);
2.sql语句

正常的insert语句

<insert id="add">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
3.提交事务
  1. SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务,这种情况不需要手动提交事务了

  2. sqlSession.commit();//手动提交事务

4.主键返回
在业务中,可能需要主键注入到对象中,融合再读取作为其他的外键

所以,我们要修改mapper里面的代码

<insert id="add" useGeneratedKeys="true" keyProperty="id">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
新增的两个属性
  1. useGeneratedKeys:是够获取自动增长的主键值。true表示获取
  2. keyProperty :指定将获取到的主键值封装到实体类对象哪儿个属性里,比如写的是"id",就类似于写到brand.id

难点4: 删除单条数据

1.编写接口方法
在 Mapper 接口中定义根据id删除方法。
/**
  * 根据id删除
  */
void deleteById(int id);
2 编写SQL语句
在 Mapper.xml 映射配置文件中编写删除一行数据的 statement
<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>

四、动态sql


1.动态多条件查询


1. 描述
在业务中,用户存在只填写一个信息,进行查询的情况,
需要我们动态去拼接statement
2.if标签
  • 使用if标签,实现条件判断,逻辑表达式写在test=" condition "里面。
  • 例子:
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="companyName != null and companyName != '' ">
            and company_name like #{companyName}
        </if>
        <if test="brandName != null and brandName != '' ">
            and brand_name like #{brandName}
        </if>
</select>
3. where 标签

在上小节内容中,还存在一个问题,如果status条件不通过,会导致sql语句存在语法问题,有两种方法解决这个逻辑运算符问题

  1. 使用恒等式 ,例如 条件中加入1=1,每个条件都用and连接
<select ...
    where 1=1
        <if test="status != null">
            and status = #{status}
     ....
</select>
  1. MyBatis中使用where标签能帮我们解决这个问题,会自动判断语句,在这个例子中,会自动帮我消去多余的and。
    例子
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="companyName != null and companyName != '' ">
            and company_name like #{companyName}
        </if>
        <if test="brandName != null and brandName != '' ">
            and brand_name like #{brandName}
        </if>
    </where>
</select>

2.动态单条件查询


1.编写mapper接口方法
由于是可选条件,所以采用传入对象方法
/**
  * 单条件动态查询
  * @param brand
  * @return
  */
List<Brand> selectByConditionSingle(Brand brand);
2. 编写sql方法
<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <choose><!--相当于switch-->
            <when test="status != null"><!--相当于case-->
                status = #{status}
            </when>
            <when test="companyName != null and companyName != '' "><!--相当于case-->
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''"><!--相当于case-->
                brand_name like #{brandName}
            </when>
        </choose>
    </where>
</select>
当然没有where标签时候是下面这样
<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    where
        <choose><!--相当于switch-->
            <when test="status != null"><!--相当于case-->
                status = #{status}
            </when>
            <when test="companyName != null and companyName != '' "><!--相当于case-->
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''"><!--相当于case-->
                brand_name like #{brandName}
            </when>
            <otherwise><!--相当于default-->
            	1=1
            </otherwise>
        </choose>
    where
</select>

3.动态update


1. 编写接口方法
 /**
   * 修改
   */
int update(Brand brand);
上述方法参数 Brand 就是封装了需要修改的数据,而id肯定是有数据的,
这也是和添加方法的区别,而且update会返回受影响行数
2.动态sql语句
<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            brand_name = #{brandName},
        </if>
        <if test="companyName != null and companyName != ''">
            company_name = #{companyName},
        </if>
        <if test="ordered != null">
            ordered = #{ordered},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="status != null">
            status = #{status}
        </if>
    </set>
    where id = #{id};
</update>
set标签的作用
  1. 解决逗号的问题
  2. 解决防止条件都不成立的问题

4.批量删除(使用动态SQL)


用到的sql:delete from table where id in (?,?,?);,其中的?是可变的

1.编写接口方法
在 Mapper 接口中定义删除多行数据的方法。
/**
  * 批量删除
  */
void deleteByIds(int[] ids);

/**
  * 使用@param注解,来重新定义map的key的名字
  */
void deleteByIds(@param("ids")int[] ids)

参数是一个数组,数组中存储的是多条数据的id

2.编写SQL语句
在 Mapper.xml 映射配置文件中编写删除多条数据的 statement。

编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用
foreach 标签

用来迭代任何可迭代的对象(如数组,集合)。

  • collection 属性:
    1. mybatis会将数组参数,封装为一个Map集合。
    2. 默认:array = 数组
    3. 使用@Param注解改变map集合的默认key的名称,"自定义名称"取代"array"
  • item 属性:本次迭代获取到的元素。
  • separator 属性:集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。
  • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
  • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">
    delete from tb_brand where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
    ;
</delete>

五、参数传递


总结以上,我们可以发现,接口方法编写的时候,为什么有的地方要加@param注解,有的地方不加,而且为什么加@param注解后,就可以使用其值,如果不加@param注解,能否表示占位参数呢?我们根据 MyBatis底层的类,可以总结以下规律

1.多个参数

Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,不加@param注解时,每个参数会加两个key,例如参数1,会加

map.put(“arg0”,参数值1);
map.put(“param1”,参数值1);

使用 @Param 注解后,Mybatis 会将 arg 开头的键名替换为对应注解的属性值。

add(@Param("name")String name,...)
map.put(“name”,参数值1);
map.put(“param1”,参数值1);

2.单个参数

  1. POJO 类型

    直接使用。要求 属性名 和 参数占位符名称 一致

  2. Map 集合类型

    直接使用。要求 map集合的键名 和 参数占位符名称 一致

  3. Collection 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

	map.put(“arg0”,collection集合);
	map.put(“collection”,collection集合;
可以使用 @Param 注解替换map集合中默认的 arg 键名。
  1. List 集合类型

    Mybatis 会将List集合封装到 map 集合中,如下:

map.put(“arg0”,list集合);
map.put(“collection”,list集合);
map.put(“list”,list集合);

可以使用 @Param 注解替换map集合中默认的 arg 键名。

  1. Array 类型

Mybatis 会将集合封装到 map 集合中,如下:

map.put(“arg0”,数组);
map.put(“array”,数组);
可以使用 @Param 注解替换map集合中默认的 arg 键名。
  1. 其他类型

    比如int类型,参数占位符名称 叫什么都可以。尽量做到见名知意

六、注解开发

查询 :@Select
添加 :@Insert
修改 :@Update
删除 :@Delete

注解完成简单功能,配置文件完成复杂功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【MyBatis】一天之内快速掌握MyBatis的增删改查 的相关文章

  • MySQL Python 关于重复键更新值

    我正在研究使用 python 将 JSON 数据上传到 MySQL 我需要在插入语句中包含 ON DUPLICATE KEY UPDATE VALUES 但在 Python 中遇到了问题 如果我运行以下代码 一切正常 import json
  • 加载数据infile,Windows和Linux的区别

    我有一个需要导入到 MySQL 表的文件 这是我的命令 LOAD DATA LOCAL INFILE C test csv INTO TABLE logs fields terminated by LINES terminated BY n
  • 日期时间与时间戳字段

    我是 MySQL 数据库的新手 您是否建议在表创建中使用日期时间或时间戳字段以及原因 我正在使用 MySQL 5 7 和 innodb 引擎 Thanks 我会用TIMESTAMP对于任何需要自动管理的事情 因为它支持诸如ON UPDATE
  • 如何为我的整个 Node.js 应用程序使用相同的 MySQL 连接?

    我有一个app js 我从那里运行我的整个应用程序 在 app js 内部 我require许多文件中都有代码 对于每个文件 我都这样做 var mysql require mysql var mclient mysql createCon
  • PDO语法错误

    我在一个项目中使用 PDO 但提交时出现语法错误 这是我的代码
  • MySQL 可选的带有 MATCH 的 LEFT JOIN

    我有以下查询 它对 MySQL Innodb 数据库中同一搜索词的两个不同表中的两列执行全文搜索 SELECT Id MATCH tb1 comment tb2 comment AGAINST search term IN BOOLEAN
  • 在同一查询中选择 Count of ip 和 Count of DISTINCT ip

    我有一个这样的表结构 TABLE NAME counter id datetime url ip 1 2013 04 12 13 27 09 url1 ip01 2 2013 04 13 10 55 43 url2 ip02 3 2013
  • 无法在 Zend Framework 中回滚事务

    我在 Zend Framework 中使用以下代码进行事务 但回滚功能不起作用 数据通过 insertSome data 插入数据库 怎么了 db gt beginTransaction try model gt insertSome da
  • MySQL“列计数与第 1 行的值计数不匹配”是什么意思

    这是我收到的消息 ER WRONG VALUE COUNT ON ROW 列计数与第 1 行的值计数不匹配 这是我的全部代码 我的错误在哪里 DROP TABLE student CREATE TABLE employee emp id I
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • MySQL 概念:会话与连接

    我对 MySQL 的概念有点困惑 会话与连接 当谈论连接到 MySQL 时 我们使用连接术语 连接池等 然而在 MySQL 在线文档中 http dev mysql com doc refman 4 1 en server system v
  • Django 将 JSON 数据传递给静态 getJSON/Javascript

    我正在尝试从 models py 中获取数据并将其序列化为views py 中的 JSON 对象 模型 py class Platform models Model platformtype models CharField max len
  • rake db 问题:迁移 -

    我无法为 Ruby on Rails 设置 MySQL 数据库 设置数据库并确保 config database yml 文件匹配后 我遇到了以下错误消息 U Rails alpha gt rake db migrate trace in
  • MySQL中查找id最大的行

    看一下下面名为 Articles 的 MySQL 表 id articleId version title content 1 1 0 0 ArticleNo 1 title v0 0 ArticleNo 1 content v0 0 2
  • 使用什么框架来引导我的第一个生产 scala 项目?

    我正在第一次涉足 scala 的生产应用程序 该应用程序当前打包为 war 文件 我的计划是创建 scala 编译工件的 jar 文件 并将其添加到 war 文件的 lib 文件夹中 我的增强功能是通过 Jersey 公开的 mysql 支
  • mysql 如何将 varchar(10) 转换为 TIMESTAMP?

    我已将所有日期存储到数据库中varchar 10 现在我想将它们转换为 TIMESTAMP 当我运行sql时 ALTER TABLE demo3 CHANGE date date TIMESTAMP NOT NULL 它提醒 1292 In
  • 如何模拟MyBatis映射器接口?

    我正在为我的 Jersey Rest API 编写单元测试 该 API 在后台使用 MyBatis 这是我的课程结构 休息服务 Path api public class HelloRestService Inject HelloBean
  • 拥有更多列或更多行会更高效吗?

    我目前正在重新设计一个可能包含大量数据的数据库 我可以选择在数据库中包含许多不同的列或使用大量行 如果我在下面做一些大纲 可能会更容易 item id user id title description content category t
  • 条件触发器的Django迁移sql

    我想创建一个触发器 仅在满足条件时插入表 我尝试过使用 IF BEGIN END 和 WHERE 的各种组合 但 Django 每次都会返回 SQL 语法错误 这里 type user id指的是触发该事件的人 user id指的是接收到通
  • 使用 PHP 将 latin1_swedish_ci 转换为 utf8

    我有一个数据库 里面充满了类似的值 Dhaka 应该是 Dhaka 因为我在创建数据库时没有指定排序规则 现在我想修复它 我无法从最初获取数据的地方再次获取数据 所以我在想是否可以在 php 脚本中获取数据并将其转换为正确的字符 我已将数据

随机推荐

  • [docker]笔记-网络管理

    1 docker网络原理 docker安装完成后 会在宿主机中创建一个虚拟网桥 用于容器之间和容器与外部网络的连接 虚拟网桥通常名称为docker0 可以使用ip link show命令进行查看 在docker中 各个容器是通过这个dock
  • 虚拟+现实

    随着现代信息技术与软硬件技术的快速发展 嵌入式系统的功能日益强大 嵌入式设备和软件应用领域越来越宽泛 近年来 嵌入式软件代码量呈爆炸式增长 对测试的要求越来越高 尤其是涉及防务 航空 汽车等安全关键领域 半实物仿真测试系统的研制难度适中 投
  • 合宙Air103

    基础资料 基于Air103开发板 Air103 LuatOS 文档 上手 开发上手 LuatOS 文档 探讨重点 对官方I2C demo中功能的复现 进行相关内容的学习及探讨 实现功能 功能2 三轴加速度陀螺仪 MPU6050模块 硬件准备
  • Typora+PicGo-Core上传服务设置

    一 Typora中安装PicGo Core 二 安装插件 Win10为例 首先点击验证图片上传选项根据提示找到安装路径 我的路径为C Users 86137 AppData Roaming Typora picgo win64 picgo
  • Qt5.14版本通用环境配置安装——最详细教学(看不懂,你怪我)

    大家好 我是会飞的鱼 blog 今天我来给大家介绍一下Qt5 14 1安装 有不足之处 请大家多多指教 感谢大家支持 目录 前言 安装文件下载 安装 设置 QtCreator 编译路径 设置 Qt 源码路径 以上就是全部安装步骤 已经完成
  • moxa串口服务器型号,moxa串口服务器产品配置说明

    moxa串口服务器产品配置说明 内容精选 换一换 为弹性云服务器配置的安全组规则未生效 以下排查思路根据原因的出现概率进行排序 建议您从高频率原因往低频率原因排查 从而帮助您快速找到问题的原因 如果解决完某个可能原因仍未解决问题 请继续排查
  • 实现一个Android锁屏App的难点总结

    http blog csdn net ldld1717 article details 69389125 https segmentfault com a 1190000007157971 自定义一个漂亮实用的锁屏app 如果能赢得用户的认
  • 第一个汇编程序hello world

    近来 看了看以下汇编视频 终于学了第一个汇编程序 hello world 下面分享以下程序的各部分代码和注释 希望大家有所帮助 程序源码如下 assume cs code ds data 定义代码段和数据段框架 data segment 数
  • 由于找不到xinput1_3.dll,无法继续执行代码的解决方法都有哪些?

    关于由于找不到xinput1 3 dll 无法继续执行代码这个问题 其实在网上经常看别人提及 要解决这个问题 还是不难的 今天小编就来给大家详细的说说关于这个问题的解决方法吧 本文会介绍多种的修复方法 下面一起来看看 一 xinput1 3
  • ubuntu 安装Nginx 以及简单配置

    Nginx使用的地方特别多 很久以前就知道Nginx使用范围很广 却并不知道Nginx具体可以做什么 怎么使用 最近读了几篇关于Nginx的文章 对Nginx有了大致的了解 只看不练无法解决真正的问题 此处主要是Nginx的安装以及 Ngi
  • 常见异常汇总

    目录 登录异常 org apache ibatis binding BindingException Invalid bound statement not found com jt mapper UserMapper findUserBy
  • MyBatis<if>标签判断字符串相等写法

    mybatis 映射文件中 if标签判断字符串相等 两种方式 因为mybatis映射文件 是使用的ognl表达式 所以在判断字符串sex变量是否是字符串Y的时候 1
  • 【数据结构】栈的代码实现

    个人博客 www hellocode top 所有文章均在上方博客首发 其他平台同步更新 本文专栏 数据结构与算法 如有问题 欢迎指正 一起学习 文章参考整理自小码哥的 恋上数据结构和算法 课程 图片转载自课程PPT 如有侵权 请联系删除
  • shell命令

    1 系统信息 arch 显示机器的处理器架构 1 uname m 显示机器的处理器架构 2 uname r 显示正在使用的内核版本 dmidecode q 显示硬件系统部件 SMBIOS DMI hdparm i dev hda 罗列一个磁
  • JAVA代码添加License

    在开源代码的时候 我们经常会在代码顶部添加License信息 每个文件复制粘贴显然是比较麻烦的 我们可以在工具中进行配置 在创建新的类的时候自动为我们添加相关信息 以eclipse为例 进入Preference gt Java gt Cod
  • SQL笔记(一)

    1 初识MySQL JavaEE 企业级Java开发 Web 前端 页面 展示 数据 后台 连接点 连接数据库JDBC 链接前端 控制 控制视图跳转 和给前端传递数据 数据库 存数据 ITxt Excel word 只会写代码 学好数据库
  • sqli-labs (less-39)

    sqli labs less 39 输入id 1 http 127 0 0 1 sql1 Less 39 id 1 根据错误显示判断为数字型注入 这里我们就不讲使用union注入的方法 前面的关卡讲了很多union注入的方法 我们直接使用堆
  • word:表格中的文字居中

    如 操作 如下图 选择布局 点击2就可以把表格居中了 居中结果
  • 实时ETL解决方案总结

    问题导读1 实时ETL可以选择哪些架构部件 2 实时ETL有哪些实现方法 3 实时ETL有哪些难点 1 简述在架构实时ETL时的可以选择的架构部件 答 在建立数据仓库时 ETL通常都采用批处理的方式 一般来说是每天的夜间进行跑批 随着数据仓
  • 【MyBatis】一天之内快速掌握MyBatis的增删改查

    MyBatis 文章介绍 一共不到8000字 一天之内可以快速学会mybatis的增删改查 以及经常使用的操作 不讲废话 只将眼光聚焦到实操上 也可以搭配黑马的视频观看 看完之后 可以自己找个mybatis源码课继续学习 但是一般的业务代码