[框架]MyBatis框架

news2024/11/18 18:30:48

关于MyBatis框架

MyBatis框架的主要作用:实现并简化数据库编程。

 

MyBatis框架的依赖项

MyBatis框架的依赖项是:mybatis,但,通常还应该再添加:mybatis-springspring-jdbcmysql或其它数据库的依赖项、数据库连接池的依赖项(commons-dbcp / commons-dbcp2 / Druid / Hikari等)、测试

在Spring Boot项目中,只需要添加mybatis-spring-boot-starter即可包含mybatismybatis-springspring-jdbc、默认的数据库连接池。

关于Mapper接口

使用MyBatis时,需要使用Mapper接口来封装访问数据的抽象方法,这些接口可以自行放在任何位置,但需要通过注解来指定,使得MyBatis框架能找到这些接口!可以:

  • 【推荐】在配置类上使用@MapperScan注解,来配置Mapper接口所在的根包(其子孙级包中的Mapper接口也会被找到)
    • 注意:配置的包下,不能有Mapper接口以外的其它接口

  • 【不推荐】在各Mapper接口上添加@Mapper注解

 所有的数据访问功能都应该在接口中定义抽象方法,关于抽象方法:

  •  返回值类型:如果需要执行的SQL语句是增、删、改类型的,应该使用`int`作为返回值类型,表示“受影响的行数”,其实也可以使用`void`,表示不关心受影响的行数,但不推荐;如果需要执行的SQL语句是查询类型的,只需要保证声明的返回值类型足以存放你需要的查询结果即可
  • 方法名称:自定义,不建议重载
《阿里巴巴Java开发手册》中的参考:
1) 获取单个对象的方法用 get 做前缀。
2) 获取多个对象的方法用 list 做前缀。
3) 获取统计值的方法用 count 做前缀。
4) 插入的方法用 save/insert 做前缀。
5) 删除的方法用 remove/delete 做前缀。
6) 修改的方法用 update 做前缀。
  • 参数列表:根据需要执行的SQL语句中的参数来设计,并且,如果参数数量较多,可以封装成自定义数据类型,并使用自定义数据类型作为方法的参数,另外,对于未封装的简单数据类型的参数(例如基本数据类型及对应的包装类、String类),只要参数的数量超过1个,强烈建议在各参数上使用@Param注解配置参数名称,例如:
void getLoginInfoByUsernameAndPassword(
    @Param("username") String username, @Param("password") String password);

关于@Param注解

通常,如果抽象方法中声明了简单类型的参数,在配置SQL语句时,可以使用#{}格式的占位符来表示参数的值,例如:

AlbumStandardVO getStandardById(Long id);
<select id="getStandardById" resultType="cn.tedu.csmall.product.pojo.vo.AlbumStandardVO">
    SELECT id, name, description, sort
    FROM pms_album
    WHERE id=#{xxx}
</select>

其实,以上配置SQL语句时,#{}中的名称是很随意的,并不一定需要是抽象方法中的参数的名称!之所以是这样,主要因为:

  • 在Java语言中,默认情况下,所有局部的量(方法内部的局部变量、方法的参数)的名称都会在编译时丢失

  • 此抽象方法只有1个参数,MyBatis会自动的去找那唯一的参数,所以,名称并不重要

由于局部的量的名称会丢失,且方法只有1个参数时,MyBatis就会使用唯一的那个参数值,但是,如果抽象方法有2个或更多个参数,MyBatis就不知道把哪个参数值传到哪个#{}占位符对应的位置!为了解决此问题,MyBatis使用了@Param注解,通过此注解来配置参数的名称,并且,在配置SQL时,应该使用注解中配置名字,例如:

AdminStandardVO getLoginInfoByUsernameAndPassword(
    @Param("username") String var1, @Param("password") String var2);
<select id="getLoginInfoByUsernameAndPassword" 
        resultType="cn.tedu.csmall.product.pojo.vo.AdminStandardVO">
    SELECT *
    FROM ams_admin
    WHERE username=#{username} AND password=#{password}
</select>

另外,在整合了Spring Boot后,使用的mybatis-spring-boot-starter对编译期进行了干预,保留了抽象方法的参数名称,所以,在Spring Boot中,即使不使用@Param注解来配置参数名称,也能够正确的找到各参数!通常,为了避免出问题,仍建议使用@Param注解配置参数名称!

关于使用注解来配置SQL语句

在使用MyBatis时,可以在抽象方法上使用@Insert / @Delete / @Update / @Select注解来配置SQL语句,例如:

public interface AlbumMapper {
    
    @Select("select count(*) from pms_album")
    int count();
    
}

但是,并不推荐使用这种做法,主要原因有:

  • 不适合编写较长篇幅的SQL语句

  • 不适合需要添加其它配置的数据访问

  • 不适合与DBA协同工作

关于使用XML来配置SQL语句

在Spring Boot项目中,需要通过配置文件中的mybatis.mapper-locations属性来配置XML文件的位置,如果使用的是MyBatis-Plus,则需要通过mybatis-plus.mapper-locations属性来配置XML文件的位置。

提示:如果使用的不是Spring Boot项目,则需要配置SqlSessionFactoryBean类型的对象来指定XML文件的位置。

在XML文件内部的配置:

  • 此文件的根标签必须是<mapper>,且必须配置namespace属性,以指定对应的Mapper接口的全限定名

  • <mapper>标签的子级,使用<insert> / <delete> / <update> / <select>标签配置SQL语句,这些标签必须配置id属性,取值为抽象方法的名称,在这些标签内部,配置抽象方法对应的SQL语句

  • 如果对应的数据表中的ID是自动编号的,在配置<insert>标签时,强烈建议配置useGeneratedKeys="true"keyProperty="id"这2个属性,以获取成功插入的数据的自动编号ID值

  • <select>标签上,必须配置resultTyperesultMap这2个属性中的其中1个,使用resultType时,取值为抽象方法的返回值类型的全限定名,使用resultMap时,取值为对应的<resultMap>标签的id属性值

  • 动态SQL之<foreach>标签:用于对参数进行遍历

    • collection属性:指定被遍历的参数,当抽象方法的参数只有1个,且没有添加@Param注解时,如果参数是List集合,则此属性取值为list,如果参数是数组或可变参数,则此属性取值为array,如果抽象方法的参数有多个或配置了@Param注解,则此属性取值为@Param注解中配置的名称

    • item属性:自定义此值,表示遍历过程中各元素的变量名

    • separator属性:遍历过程中生成各值时,各值之间的分隔符号

  • 动态SQL之<if>标签:用于对参数进行判断,例如:

<!-- int update(Album album); -->
<update id="update">
    UPDATE 
    	pms_album
    <set>
    	<if test="name != null">
    		name=#{name},
        </if>
    	<if test="description != null">
    		description=#{description},
        </if>
        <if test="sort != null">
    		sort=#{sort},
        </if>
    </set>
    WHERE
    	id=#{id}
</update>

动态SQL之<choose>系列标签,用于实现类似Java语言中if...else的效果,例如:

<choose>
	<when test="条件">
    	满足条件时的代码片段
    </when>
    <otherwise>
    	不满足条件时的代码片段
    </otherwise>
</choose>

<sql>标签与<include>标签,用于封装SQL语句片段(通常是字段列表)并引用封装的SQL语句片段,例如:

<!-- List<RoleListItemVO> list(); -->
<select id="list" resultType="cn.tedu.csmall.passport.pojo.vo.RoleListItemVO">
    SELECT
        <include refid="ListItemQueryFields"/>
    FROM
        ams_role
    ORDER BY
        sort DESC, id
</select>

<sql id="ListItemQueryFields">
    id, name
</sql>

提示:在IntelliJ IDEA中,在<sql>标签中直接写字段列表会提示错误,但这并不影响运行,如果不希望看到报错的红色波浪线,可以改为:

<sql id="ListItemQueryFields">
    <if test="true">
        id, name
    </if>
</sql>

[SpringBoot]xml写mapper&设置自动提示_万物更新_的博客-CSDN博客

 

MyBatis的缓存机制

MyBatis框架存在缓存机制,表现为:当执行查询后,可以将查询结果暂时保存到应用程序服务器中(即使返回了查询结果,也不会销毁这个数据),后续再次查询时,就可以将此前的查询结果直接返回,以此提高“查询”效率。

MyBatis框架有2种缓存机制,分别称之为一级缓存和二级缓存。

一级缓存也称之为“会话缓存”,它是基于SqlSession的,默认是开启的,且无法关闭,当使用同一个Mapper、执行同样的查询、传递的是同样的参数时,后续的查询将直接返回前序的查询结果。

一级缓存的结果会因为手动清除(调用SqlSession对象的clearCache()方法)而消失,也会因为此Mapper执行了任何写操作(增、删、改)而自动清除,无论这个写操作是否改变了任何数据!

关于一级缓存的示例:

@Autowired
SqlSessionFactory sqlSessionFactory;

@Test
void l1Cache() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    AlbumMapper albumMapper = sqlSession.getMapper(AlbumMapper.class);

    System.out.println("准备执行第1次查询……");
    Object queryResult1 = albumMapper.getStandardById(1L);
    System.out.println("第1次查询结束!");
    System.out.println(queryResult1);

    System.out.println("准备执行第2次查询……");
    Object queryResult2 = albumMapper.getStandardById(1L);
    System.out.println("第2次查询结束!");
    System.out.println(queryResult2);

    // 清除此前的缓存结果
    // sqlSession.clearCache();
    albumMapper.deleteById(13000000L);

    System.out.println("准备执行第3次查询……");
    Object queryResult3 = albumMapper.getStandardById(1L);
    System.out.println("第3次查询结束!");
    System.out.println(queryResult3);

    System.out.println("准备执行第4次查询……");
    Object queryResult4 = albumMapper.getStandardById(2L);
    System.out.println("第4次查询结束!");
    System.out.println(queryResult4);

    System.out.println("准备执行第5次查询……");
    Object queryResult5 = albumMapper.getStandardById(1L);
    System.out.println("第5次查询结束!");
    System.out.println(queryResult5);
}

二级缓存也称之为“namespace缓存”,是基于namespace的(其实就是配置SQL的XML对应的Mapper),在Spring Boot中,默认全局开启,但各namespace默认并未开启,可以在XML文件中添加<cache/>标签以开启当前XML对应的Mapper的二级缓存,只要是同样的查询,且传入的参数相同,后续的查询就可以直接使用前序的查询结果。

 

二级缓存也会因为调用了此XML中的任何写数据的操作而清除!

注意:二级缓存还可以通过在<select>标签上配置useCache属性来开启或关闭,默认取值为true

注意:当使用二级缓存后,查询结果的类型必须实现Serializable接口,如果没有实现,在查询时会抛出NotSerializableException异常!

二级缓存的示例代码:

@Autowired
AlbumMapper albumMapper;

@Test
void l2Cache() {
    System.out.println("准备执行第1次查询……");
    Object queryResult1 = albumMapper.getStandardById(1L);
    System.out.println("第1次查询结束!");
    System.out.println(queryResult1);

    System.out.println("准备执行第2次查询……");
    Object queryResult2 = albumMapper.getStandardById(1L);
    System.out.println("第2次查询结束!");
    System.out.println(queryResult2);

    // albumMapper.deleteById(12L);

    System.out.println("准备执行第3次查询……");
    Object queryResult3 = albumMapper.getStandardById(1L);
    System.out.println("第3次查询结束!");
    System.out.println(queryResult3);

    System.out.println("准备执行第4次查询……");
    Object queryResult4 = albumMapper.getStandardById(2L);
    System.out.println("第4次查询结束!");
    System.out.println(queryResult4);

    System.out.println("准备执行第5次查询……");
    Object queryResult5 = albumMapper.getStandardById(1L);
    System.out.println("第5次查询结束!");
    System.out.println(queryResult5);
}

MyBatis在每次查询时,都会优先检查二级缓存,如果命中,将直接返回缓存结果,如果未命中,则会检查一级缓存,如果仍未命中,才会执行真正的查询。

关于命中率:

 

 

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

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

相关文章

FreeRTOS_列表和列表项

目录 1. 什么是列表和列表项&#xff1f; 1.1 列表 1.2 列表项 1.3 迷你列表项 2. 列表和列表项初始化 2.1 列表初始化 2.2 列表项初始化 3. 列表项插入 3.1 列表项插入函数分析 3.2 列表项插入过程图示 3.2.1 插入值为 40 的列表项 3.2.2 插入值为 60 的列表项 3…

c++ while(i--) 的执行顺序

问&#xff1a;while (i--) {语句B} 的执行顺序是什么&#xff1f; 首先执行i--,再执行 while ,再执行语言B. 一个案例&#xff1a; 案例中count 的初始值为-3. 第一个打出的为-2&#xff0c; 证明的之前的判断流程。 附录&#xff1a; while(条件){//语句A} 的执行逻辑&…

聊聊PCIe协议的BDF

[摘要]&#xff1a;本文主要介绍 PCIe 协议中 Bus、Device 和 Function 的基本定义。 PCIe 总线的拓扑结构就像一颗葡萄树&#xff1a;树根相当于 PCIe Root Complex&#xff0c;树干和树枝相当于 PCIe Bus&#xff0c;一整串葡萄相当于 PCIe Device&#xff0c;一颗葡萄相当于…

c++构造基类

c构造基类 c构造基类采用初始化列表 基类的成员变量由基类的构造函数初始化 派生类的成员变量由派生类的构造函数初始化 基类&#xff1a; 派生类: 调用

微信扫码对接

微信扫码对接&#xff0c;如果刚开始没有资源进行对接。 可以选择先申请微信公众测试平台进行测试&#xff0c;地址如下 微信公众平台 申请步骤等等简单的就不说了&#xff0c;本文主要说一下需要注意的坑。 1.首先需要一个外网地址&#xff0c;做本地映射&#xff0c;否则…

掌握这些容易被忽略的Vue组件细节,提升开发效率,事半功倍!

组件允许我们将 UI 划分为独立的、可重用的部分&#xff0c;并且可以对每个部分进行单独的思考。 组件在日常开发的重要性不言而喻&#xff0c;掌握下述细则&#xff0c;可以让你在开发中事半功倍&#xff01; Props defineProps() 宏中的参数不可以访问 <script setup&…

mysql的高可用架构之mmm

目录 一、mmm的相关知识 1&#xff09;mmm架构的概念 2&#xff09;MMM 高可用架构的重要组件 3&#xff09;mmm故障切换流程 二、mmm高可用双主双从架构部署 实验设计 实验需求 实验组件部署 具体实验步骤 步骤一&#xff1a; 搭建 MySQL 多主多从模式 &#…

Uniapp中简单弹出层的使用

图示 思路 当派工单这个输入框获取到焦点后&#xff0c;弹出弹出层选择数据。 1、定义这个输入框 <view class"cu-form-group"><view class"title"><text class"text-red">*</text>派工单号: </view><input…

Mysql查询语句优化方法

查询优化 小表驱动大表 优化原则&#xff1a;对于MySQL数据库而言&#xff0c;永远都是小表驱动大表。 /** * 举个例子&#xff1a;可以使用嵌套的for循环来理解小表驱动大表。 * 以下两个循环结果都是一样的&#xff0c;但是对于MySQL来说不一样&#xff0c; * 第一种可以理解…

第1章-Java语言概述

Java基础知识图解 1. Java语言概述 1.1 Java简史 是SUN(Stanford University Network&#xff0c;斯坦福大学网络公司 ) 1995年推出的一门高级编程语言。是一种面向Internet的编程语言。 Java一开始富有吸引力是因为Java程序可以在Web浏览器中运行。 这些Java程序被称为Java小…

DepthAI API详解

目录 DepthAI的整体架构Device 对象通过标识连接到指定设备定义输入/输出队列Device对象的常用方法addLogCallback()方法close()方法getInputQueue()方法getOutputQueue()方法 PipelinePipeline常用的方法create()方法createColorCamera()方法createMonoCamera()方法createNeur…

泛微以低代码助力央企合规、案件管理数字化

近年来&#xff0c;国家出台一系列文件&#xff0c;不断强化央企国企合同、法务、合规、风控一体化管理&#xff0c;深化法治企业建设。 2022年&#xff0c;国资委印发《中央企业合规管理办法》&#xff0c;要求中央企业加强合规管理&#xff0c;切实防控风险&#xff0c;并指…

新手小白学JAVA_IDEA修改主题 设置背景图片

很多小白在刚刚使用IDEA的时候还不是很熟练 本文主要给大家提供一些使用的小技巧&#xff0c;希望能帮助到你 1.修改IDEA默认主题 IDEA的默认主题是黑色的&#xff0c;其实也可以选择其他的主题 我们一起来试一试吧~ 2.修改IDEA背景图片 IDEA的背景图片也是可以自定义的 我们…

arcgis波段提取--多波段合成

1、打开软件&#xff0c;导入彩色栅格影像&#xff0c;如下&#xff1a; 上图有RGB三个波段&#xff0c;在左侧图层下可以看到波段情况。 2、在菜单栏中选择"窗口"--"影像分析"&#xff0c;如下&#xff1a; 点击影像分析功能&#xff0c;打开如下界面&am…

移除flyway,手动进行数据库的迁移

国产数据库如达梦、金仓数据库&#xff0c;开源数据迁移工具貌似支持的很少&#xff0c;手写工具类进行数据库脚本的迁移&#xff0c;主要有2个类如下&#xff1a; /*** 模拟flyway进行sql迁移*/ Component Slf4j public class SqlInitialize implements InitializingBean, Ord…

Java【String字符串不可变】

字符串不可变&练习 字符串不可变1. 字符串设置为不可变的原因2. 如何修改字符串内容3 StringBuilder类的具体使用4. 面试题 字符串不可变 1. 字符串设置为不可变的原因 方便实现字符串常量池&#xff0c;若String对象可变&#xff0c;常量池中的内容就会随时变化&#xf…

Linux SVN提交日志校验

#!/bin/bash export LANG"en_US.UTF-8" #确保中文日志显示正常&#xff0c;便于统计日志 REPOS"$1" TXN"$2" #限制日志长度 LENGTH20 #exit 0SVNLOOK"/usr/bin/svnlook" BLACKLIST".* *.o *.chw *.pck ~\$*"function error_…

五、菜单管理

云尚办公系统&#xff1a;菜单管理 B站直达【为尚硅谷点赞】: https://www.bilibili.com/video/BV1Ya411S7aT 本博文以课程相关为主发布&#xff0c;并且融入了自己的一些看法以及对学习过程中遇见的问题给出相关的解决方法。一起学习一起进步&#xff01;&#xff01;&#x…

【Linux系统编程】Linux基本指令详解(二)

文章目录 前言1. cp 指令&#xff08;重要&#xff09;2. mv 指令&#xff08;重要&#xff09;3. cat 指令echo 命令输出重定向追加重定向wc 命令输入重定向 4. more 指令5. less指令&#xff08;重要&#xff09;6. head指令7. tail指令8. 命令行管道&#xff08;了解&#x…

《AVL树》

文章目录 一、AVL树的基本概念二、AVL树的结点定义三、AVL树的插入四、AVL树的旋转1. 右单旋2. 左单旋3. 右左双旋4. 左右双旋 五、AVL树的验证六、AVL树的性能七、源代码 一、AVL树的基本概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将…