系统回顾MyBatis体验这一优秀的持久层框架

news2024/11/20 3:28:38

文章目录

    • 1.MyBatis
    • 2.Mapper代理
    • 3.MyBatis配置升级
    • 4.配置文件CRUD
    • 5.多条件查询
    • 6.多条件动态查询
    • 7.单条件动态条件查询
    • 8.添加数据并主键返回
    • 9.更新数据
    • 10.删除数据
    • 11.参数传递
    • 12.注解开发

1.MyBatis

MyBatis基本上取消了所有的JDBC硬编码,对于单独使用这样的ORM框架,只需要:
1.导入maven坐标

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.30</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.10</version>
</dependency>

2.编写配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///ssm?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="284650"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="BookMapper.xml"/>
    </mappers>
</configuration>

3.编写对应的Mapper映射文件,SQL都写在了配置文件里,每一句SQL都有所属的命名空间、id、resultType这都是在代码中准确定位并执行的保障

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BookTest">
    <select id="selectAllBook" resultType="com.yu7.Pojo.Book">
        select * from ssm_db
    </select>
</mapper>

4.写Java代码执行sql

//加载myBatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取SqlSession对象,用来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql
List<Book> bookList = sqlSession.selectList("BookTest.selectAllBook");
System.out.println(bookList);
sqlSession.close();

2.Mapper代理

上述的快速入门其实还是存在一定的硬编码,我们可以通过Mapper代理的方式进一步简化,官网里是这样说的:
在这里插入图片描述

如何实现Mapper代理?
在这里插入图片描述
1.定义一个Mapper接口,并将接口和SQL映射文件放在同一目录下,可以把配置文件放在Java代码中但不推荐,也可以在配置文件Resource里创建相同的目录结构,要注意目录层次要用"/",而不能用”.“,才能保证mapper文件和.class文件在同一目录下,要不然目录结构不匹配会导致Mapper代理不成功
在这里插入图片描述
正确的方式编译过后这两个文件才会在一个目录下
在这里插入图片描述
2.mapper文件的命名空间为接口的全限名
在这里插入图片描述
并修改原先mybatis-config.xml里的sql映射文件路径

其实,当你的mapper接口都按照规范写在一块儿,就不用针对不同的mapper来写不同的SQL映射,直接可以这样写:
在这里插入图片描述

3.在mapper接口里写方法(在配置文件里已经定义)
在这里插入图片描述
4.通过Mapper代理的方式执行SQL

//加载myBatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

//获取SqlSession对象,用来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();

//通过Mapper代理来执行SQL
BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);
List<Book> bookList = bookMapper.selectAllBook();

System.out.println(bookList);
sqlSession.close();

总结起来,就是MyBatis-config.xml里配置的连接信息被加载,加载完之后加载mapper标签中的sql映射文件(xxxMapper.xml),在那里面有不同的命名空间并且其中都有着各种各样标注着id、resultType的sql片段。当这些东西被加载完以后,我就可以在接口里定义和sql映射文件中id一致的方法来完成对数据库的操作。

3.MyBatis配置升级

!!!配置要讲究顺序!!!

1.多数据源配置
在这里插入图片描述
2.类型别名
为了让我们书写更方便,基本类型会自动配置,自定义的类型可以自己一个一个的配 也可以使用包扫描的方式

在这里插入图片描述

在mybatis-config配置文件中,我们可以通过typeAliases标签来给映射类型取别名(包扫描)

<typeAliases>
    <package name="com.yu7.Pojo"/>
</typeAliases>

这样SQL映射文件里的resultType属性就可以直接用别名了(不区分大小写),而不需要像以前那样用包路径名(com.yu7.Pojo.Book)
在这里插入图片描述

4.配置文件CRUD

要想写好CRUD必须要弄清楚三件事1.SQL咋写2.完成业务要不要参数3.结果参数怎么处理
sql片段
解决数据库表字段与实体不对应,提升开发效率

<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>

ResultMap

其实前面的在SQL映射文件里写resultType不好,可以在Mapper.xml配置文件中使用resultMap,并且可以在标签里给表中的字段起别名来解决表与实体不匹配的问题,就像这样:
在这里插入图片描述
一些特殊情况

参数占位符:
    1. #{}:执行SQL时会将#{}替换为 ?,可以防止SQL注入
    2. ${}:拼sql。会存在SQL注入问题
    3. 使用时机:
        * 参数传递的时候:#{}
        * 表名或者列名不固定的情况下:${} 会存在SQL注入问题

 * 参数类型:parameterType:可以省略
 * 特殊字符处理: 比如在SQL里就不能写 < 所以使用转义字符或者CDATA区来解决
    1. 转义字符:
    2. CDATA区:

5.多条件查询

多条件模糊查询场景

<select id="selectByCondition" resultMap="brandResultMap">
     select *
     from tb_brand
     where status = #{status}
       and company_name like #{companyName}
       and brand_name like #{brandName}
 </select>

1.对接收参数的处理
在这里插入图片描述2.散装参数:如果方法中有多个参数,需要使用@Param(“SQL参数占位符名称”) 用它将形参列表里的参数与mapper文件里sql中的占位符参数映射一致

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

3.对象参数:对象的属性名称要和参数占位符名称一致
将参数封装成一个对象,方法通过接收对象来进行查询

 //封装对象
 Brand brand = new Brand();
 brand.setStatus(status);
 brand.setCompanyName(companyName);
 brand.setBrandName(brandName);

4.map集合参数

Map map = new HashMap();
map.put("status" , status);
map.put("companyName", companyName);
map.put("brandName" , brandName);

在这里插入图片描述

6.多条件动态查询

用户输入的值不一样,对应的SQL不一样

上述的查询存在弊端,当用户查询的值和方法接收的参数不匹配或者接收的空值就会导致执行的SQL过不了语法,因此需要对接收的参数做检验来动态地查询

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    /* where 1 = 1*/
    <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>

如果第一个if不生效,那么SQL语法就错误了,为了解决这一问题,可以使用恒等式或者,当第一个if不生效,它会自动帮你去掉and并且会自动生成where关键字

7.单条件动态条件查询

用户选择一个类型来进行单条件查询,当用户一个条件都不选,标签会自动识别并去掉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>
        </choose>
    </where>
</select>

8.添加数据并主键返回

使用useGeneratedKeys=“true” keyProperty=“id”

void add(Brand brand);
<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>
sqlSession.commit();

记得提交事务

9.更新数据

更新全部字段,动态更新字段,使用动态SQL通用性强。使用固定字段,如果有些字段没有更新可能会被改成Null所以不推荐

<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>

10.删除数据

删除一条数据

<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>

删除多条数据:把接收到的参数封装成一个数组,遍历数组一个一个删除

void deleteByIds(int[] ids);
<!--
    mybatis会将数组参数,封装为一个Map集合。
        * 默认:array = 数组 键是array 值是数组
        * 使用@Param注解改变map集合的默认key的名称
	    * collection="array"表示遍历键为array的值,也就是数组
-->
<delete id="deleteByIds">
    delete from tb_brand where id
    in
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
         ;
</delete>
open="(" close=")"可以自动拼括号

不过还有一种写法:
在这里插入图片描述

11.参数传递

当我们在mapper接口的方法里接收多个参数时,需要使用@Param注解来将接收的参数和mapper文件里的占位符中参数保持一致,这是因为myBatis底层会对接收到的多个参数进行封装,并且封装成map,其中k为arg0,param1,param2…,很显然如果你不写注解,底层就会默认帮你封装,这就会导致与mapper文件里占位符中的参数不一致,从而导致占位符中的值都为null !

针对不同类型都有不同的封装策略,要根据实际情况来看是否需要写注解

MyBatis 参数封装:
  * 单个参数:
      1. POJO类型:直接使用,属性名 和 参数占位符名称 一致
      2. Map集合:直接使用,键名 和 参数占位符名称 一致
      3. Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
          map.put("arg0",collection集合);
          map.put("collection",collection集合);
      4. List:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
          map.put("arg0",list集合);
          map.put("collection",list集合);
          map.put("list",list集合);
      5. Array:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
          map.put("arg0",数组);
          map.put("array",数组);
      6. 其他类型:直接使用
  * 多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
      map.put("arg0",参数值1)
      map.put("param1",参数值1)
      map.put("param2",参数值2)
      map.put("agr1",参数值2)
      ---------------@Param("username")
      map.put("username",参数值1)
      map.put("param1",参数值1)
      map.put("param2",参数值2)
      map.put("agr1",参数值2)

12.注解开发

看博主懒羊羊.java以前写的MyBatis博客
切记,注解开发只适用于一些简单的功能,复杂的功能还是用配置文件吧

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

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

相关文章

1585_AURIX_TC275_SMU的部分内核寄存器

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 继续看SMU的资料&#xff0c;这次看一部分SMU的内核相关寄存器。这一次整理的内容比较少&#xff0c;而且优点断篇&#xff0c;因此按照序号来分没有保持10页的对齐。 调试相关的寄存器不…

详解外网访问内网DDNS作用 及ddns解析软件使用方法

导语&#xff1a;随着互联网的成熟&#xff0c;家庭宽带的提速&#xff0c;大家对外网访问家庭内网电脑&#xff0c;监控&#xff0c;服务器&#xff0c;存储NAS等设备的需求倍增。目前外网访问内网可以用DDNS动态域名解析的方式&#xff0c;以下本文就来介绍一下原理和实现工具…

ELK日志(3)

EFK日志收集 Elasticsearch: 数据库&#xff0c;存储数据 javalogstash: 日志收集&#xff0c;过滤数据 javakibana: 分析&#xff0c;过滤&#xff0c;展示 javafilebeat: 收集日志&#xff0c;传输到ES或logstash go redis&#xff1a;缓冲数据&#xff0c;等待logstash取数据…

高并发多级缓存架构解决方案 OpenResty、canal搭建及使用流程

高并发多级缓存架构解决方案1、缓存的常规使用方式2、请求流程拆分1、搭建tomcat集群2、搭建OpenRestyOpenResty的目录结构nginx的配置文件lua脚本的执行流程http请求反向代理到tomcat服务器3、OpenResty、Redis的单点故障问题4、防止缓存穿透java中通过redisson实现布隆过滤器…

Mac 下配置 go语言环境

Mac 下配置 go语言环境两种方法安装Go通过Homebrew安装&#xff08;不太推荐&#xff09;通过官网安装 &#xff08;推荐&#xff09;方法一安装Homebrew通过Homebrew安装Go方法二 通过官网进行安装配置go环境配置go环境国内镜像Vscode环境配置Helloworld.go两种方法安装Go 通…

LabVIEW中的VI脚本

LabVIEW中的VI脚本用户可使用VI脚本选板上的VI、函数和相关的属性、方法&#xff0c;通过程序创建、编辑和运行VI。通过VI脚本&#xff0c;可减少重复的VI编辑所需的时间&#xff0c;例如&#xff1a;创建若干类似VI对齐和分布控件显示或隐藏控件标签连接程序框图对象注: 必须先…

【13】Docker_DockerFile | 关键字

目录 1、DockerFile的定义 2、DockerFile内容基本知识 3、Docker执行DockerFile的大致流程 4、DockerFile的关键字 5、举例&#xff1a; 1、DockerFile的定义 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 2、Do…

[前端笔记——HTML介绍] 2.开始学习HTML

[前端笔记——HTML介绍] 2.开始学习HTML1什么是HTML&#xff1f;2剖析一个HTML元素3块级元素和内联元素4空元素5属性6为一个元素添加属性7布尔属性8省略包围属性值的引号9单引号或双引号?10剖析HTML文档11实体引用&#xff1a;在 HTML 中包含特殊字符1什么是HTML&#xff1f; …

LeetCode 17. 电话号码的字母组合

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 17. 电话号码的字母组合&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 17.…

文件操作中的IO流——字节流与字符流

一&#xff0c;IO流1.什么是IO流IO流是存取和读取数据的解决方案2.IO流的作用IO流用于读写数据&#xff0c;这些数据包括本地文件和网络上的一些数据&#xff1b;比如读写本地文件的时候需要用到文件读写的IO流&#xff0c;读写网络上的数据时需要通过Socket套接字来调用数据流…

机器学习:公式推导与代码实现-监督学习单模型

线性回归 线性回归(linear regression)是线性模型的一种典型方法。 回归分析不再局限于线性回归这一具体模型和算法,更包含了广泛的由自变量到因变量的机器学习建模思想。 原理推导 线性回归学习的关键问题在于确定参数w和b,使得拟合输出y与真实输出yi尽可能接近 为了求…

PowerDesigner16.5配置安装与使用

PowerDesigner16.5百度云下载链接 链接&#xff1a;https://pan.baidu.com/s/1b9XUqxVZ8gTqk_9grptcAQ?pwd3pl7 提取码&#xff1a;3pl7 一&#xff1a;软件安装 1.下载安装包&#xff08;包含安装文件、汉化包、注册文件&#xff09; 2.下载后文件内容如下 3.进入安装文件中…

5. 统计学基础1:平均值...四分位数、方差、标准差(均方差)、标准误(标准误差、均方根误差)、 标准分

文章目录1. 平均值、中位数、众数、极差、四分位数&#xff08;即下、中、上四份位数&#xff09;2. 方差&#xff08;Var、D(X) 、σ^2^&#xff09;、标准差【也叫均方差】&#xff08;SD 、σ&#xff09;3. 标准误【也叫标准误差、均方根误差】&#xff08;SE&#xff09;4…

高空探测数据处理--对流层顶选取

对流层的概念(维基百科) 对流层(英语:Troposphere)是地球大气层中最靠近地面的一层,也是地球大气层里密度最高的一层。它蕴含了整个大气层约75%的质量,以及几乎所有的水蒸气及气溶胶。 对流层从地球表面开始向高空伸展,直至对流层顶,即平流层的起点为止。对流层的上…

【Labview】每日一题

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

The ATIS Spoken Language Systems Pilot Corpus

摘要 语音研究有巨大的进步在过去使用以下的模式: 定义研究问题收集语料针对性的衡量进展解决这个研究问题 自然语言研究&#xff0c;另一方面&#xff0c;取得了典型的进步在没有任何数据语料的情况下&#xff0c;这能够测试研究的假设。 我们描述了ATISATISATIS试点语料库…

从C到C++及类与对象

目录 从C到C 嵌入式领域常用的GUI 语法的升级 引用 默认参数 函数重载 堆内存 概念和思维的升级 类和对象 类的申明 类的成员函数 常成员、常对象&#xff08;C推荐const而不用#define&#xff0c; mutable &#xff09; 静态成员(属于类不属于对象) 友元(破坏…

Opencv实战案例——模板匹配实现银行卡号识别(附详细介绍及完整代码下载地址)

Opencv目录1.项目意义2.模板匹配3.图像二值化3.1全局阈值3.2全局阈值代码即效果展示3.3 自适应阈值3.4自适应阈值代码即效果展示4.轮廓筛选4.1轮廓检测4.2绘制轮廓4.3轮廓筛选代码及效果展示5.形态学变化5.1腐蚀5.2膨胀5.3开运算和闭运算、礼帽和黑帽6.项目实战6.1读取图片转化…

next_permutation函数讲解

目录 前言&#xff1a; 简要概述&#xff1a; 例题&#xff08;1&#xff09;&#xff1a; P1088 [NOIP2004 普及组] 火星人 题目描述 输入格式 输出格式 输入输出样例 说明/提示 代码&#xff08;1&#xff09;&#xff1a; 例题&#xff08;2&#xff09;&#xf…

如何开发 Vite 3 插件构建 Electron 开发环境?(文末附视频讲解)

开发新版本 Vue 项目推荐你使用 Vite 脚手架构建开发环境&#xff0c;然而 Vite 脚手架更倾向于构建纯 Web 页面&#xff0c;而不是桌面应用&#xff0c;因此开发者要做很多额外的配置和开发工作才能把 Electron 引入到 Vue 项目中&#xff0c;这也是很多开发者都基于开源工具来…