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

相关推荐
骑鱼过海的猫1231 分钟前
【java】java通过s3访问ceph报错
java·ceph·iphone
杨充7 分钟前
13.观察者模式设计思想
java·redis·观察者模式
Lizhihao_9 分钟前
JAVA-队列
java·开发语言
喵叔哟19 分钟前
重构代码之移动字段
java·数据库·重构
喵叔哟19 分钟前
重构代码之取消临时字段
java·前端·重构
fa_lsyk21 分钟前
maven环境搭建
java·maven
念白44322 分钟前
智能病历xml提取
数据库·sql·oracle
qingy_204626 分钟前
【JavaWeb】JavaWeb入门之XML详解
数据库·oracle
大数据面试宝典30 分钟前
用AI来写SQL:让ChatGPT成为你的数据库助手
数据库·人工智能·chatgpt
努力的小雨35 分钟前
快速上手 KSQL:轻松与数据库交互的利器
数据库·经验分享