MyBatis系列

一:Mybatis中#{}和${}的区别

1、#{}是预编译处理,${}是字符串替换。

2、Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的 set方法来赋值;

3、Mybatis在处理{}时,就是把{}替换成变量的值。

4、使用#{}可以有效的防止SQL注入,提高系统安全性。

二:Mybatis的执行流程

1、读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配 置了 MyBatis 的运行环境等信息,例如数据库连接信息。

2、加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在MyBatis 配置文件 mybatis-config.xml 中加载。 mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张 表。

3、构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

4、创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

5、Executor执行器:MyBatis底层定义了一个Executor 接口来操作数据库,它将 根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存 的维护。

6、MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。

7、输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本 数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对 象设置参数的过程。

8、输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本 数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

三:Mybatis如何获取生成的主键

使用insert标签中的useGeneratedKeys和keyProperty 属性

XML 复制代码
<insert id = "saveUser" useGeneratedKeys = "true" KeyProperty = "id">
     insert into tb_user(user_name,password,gender,addr) values(#{username},#{password},#{gender},#{addr})
</insert>

属性说明:

1、useGeneratedKeys:是够获取自动增长的主键值。true表示获取。

2、keyProperty :指定将获取到的主键值封装到哪儿个属性里

四:JDBC有什么缺点,Mybatis是如何解决的

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解 决此问题。 解决:在mybatis-config.xml中配置数据链接池,使用连接池管理数据库连接。

2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代 码。 解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参 数一一对应。 解决: Mybatis自动将java对象映射至sql语句。

4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装 成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象

五:为什么需要预编译

定义:

SQL 预编译指的是数据库驱动在发送 SQL 语句和参数给 DBMS 之前对 SQL 语句进行编译, 这样 DBMS 执行 SQL 时,就不需要重新编译。

为什么需要预编译:

JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译。预编译阶段可以优 化 SQL 的执行。预编译之后的 SQL 多数情况下可以直接执行,DBMS 不需要再次编译,越 复杂的SQL,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。同时预编译 语句对象可以重复利用。把一个 SQL 预编译后产生的 PreparedStatement 对象缓存下来, 下次对于同一个SQL,可以直接使用这个缓存的 PreparedState 对象。Mybatis默认情况下, 将对所有的 SQL 进行预编译。 还有一个重要的原因,防止SQL注入

六:Mybatis如何进行批量操作

使用foreach标签

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach标签的属性主 要有item,index,collection,open,separator,close。

item 表示集合中每一个元素进行迭代时的别名,随便起的变量名;

index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置,不常用;

open  表示该语句以什么开始,常用"(";

separator 表示在每次进行迭代之间以什么符号作为分隔符,常用",";

close   表示以什么结束,常用")"。

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是 在不同情况下,该属性的值是不一样的,主要有一下3种情况:

  1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list

  2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array

  3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封 装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map 的, map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封 装的map里面的key

XML 复制代码
<!-- 批量保存(foreach插入多条数据两种方法)
       int addEmpsBatch(@Param("emps") List<Employee> emps); -->
 <!-- MySQL下批量保存,可以foreach遍历 mysql支持values(),(),()语法 --> //推荐使用
<insert id="addEmpsBatch">
    INSERT INTO emp(ename,gender,email,did)
    VALUES
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id})
    </foreach>
 </insert>
XML 复制代码
<!-- 这种方式需要数据库连接属性allowMutiQueries=true的支持
 如jdbc.url=jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true -->  
<insert id="addEmpsBatch">
    <foreach collection="emps" item="emp" separator=";">                         
        
        INSERT INTO emp(ename,gender,email,did)
        VALUES(#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id})
    </foreach>
 </insert>

七:实体类的属性名和表字段中的名称不一样,怎么解决

第1种: 通过在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致

XML 复制代码
<select id="getOrder" parameterType="int" 
resultType="com.jourwon.pojo.Order">
 select order_id id, order_no orderno ,order_price price form orders 
where order_id=#{id};
 </select>

第2种: 通过 来映射字段名和实体类属性名的一一对应的关系。

XML 复制代码
<select id="getOrder" parameterType="int" resultMap="orderResultMap">
 select * from orders where order_id=#{id}
 </select>
 <resultMap type="com.jourwon.pojo.Order" id="orderResultMap">
 <!--用id属性来映射主键字段-->
 <id property="id" column="order_id">
性-->
 <!--用result属性来映射非主键字段,property为实体类属性名,column为数据库表中的属
<result property ="orderno" column ="order_no"/>
 <result property="price" column="order_price" />
 </reslutMap>

八:什么是Mybatis的接口绑定,有哪几种实现方式

接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调 用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。

接口绑定有两种实现方式

  1. 通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来 绑定;

  2. 通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为 接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml 绑定,一般用xml绑定的比较多

九:Mybatis的一级缓存和二级缓存

  1. 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session f lush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其 存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓 存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状 态),可在它的映射文件中配置 3. 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear

十:Mybatis是如何进行分页的,原理是什么

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截 待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student) t limit 0, 10

相关推荐
熊大如如19 分钟前
Java 反射
java·开发语言
巨龙之路31 分钟前
什么是时序数据库?
数据库·时序数据库
蔡蓝36 分钟前
binlog日志以及MySQL的数据同步
数据库·mysql
猿来入此小猿38 分钟前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo1 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder1 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
是店小二呀1 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
pjx9872 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka
炒空心菜菜2 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark
多多*2 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle