Mybatis基础

本文详细介绍了MyBatis的核心概念、XML和注解配置、SQL注入防护、优点与缺点、分页与一对一映射、延迟加载、缓存机制以及与SpringBoot的集成,涵盖了设计模式在MyBatis中的应用。
摘要由CSDN通过智能技术生成

一、什么是MyBatis

1 Mybatis 是一个半 ORM (对象关系映射)框架,它内部封装了 JDBC ,开发时只需要关注 SQL
语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直
接编写原生态 sql ,可以严格控制 sql 执行性能,灵活度高。
2 MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避 免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3 )通过 xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为java 对象并返回。(从执行 sql 到返回 result 的过程)。

二、Mybatis#$区别是什么?

#{} 是预编译处理, ${} 是字符串替换 。
Mybatis 在处理 #{} 时,会将 sql 中的 #{} 替换为 ? 号,调用PreparedStatement的 set 方法来赋值;
Mybatis 在处理 ${} 时,就是把 ${} 替换成变量的值。所以有 SQL 注入漏洞问题。
结论:
使用 #{} 可以有效的防止 SQL 注入,提高系统安全性。但是 $ 在保证安全的情况下,也有一些使用场景,比如:$ 符号的动态传参 ,动态传递表名、动态设置排序字段等。

三、Mybatis的优缺点

优点:
1 )基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响, SQL 写 在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
(2 )与 JDBC 相比,减少了 50% 以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;
(3 )很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
4 )能够与 Spring 很好的集成;
5 )提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象 关系组件维护。
缺点:
1 SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 SQL 语句的功底有一定要求。
(2 SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

四、当实体类中的属性名和表中的字段名不一样处理方式

1 种: 通过在查询的 sql 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
2 种: 通过来映射字段名和实体类属性名的一一对应的关系。

五、Mybatis是如何进行分页的?分页插件的原理是什么?

使用 mybatis 整合 pageHelper 或者 mybatisPlus 的分页功能,他是基于 Mybatis 里面的
Interceptor 拦截器 ,在 select 语句执行之前动态拼接分页关键字。查询执行日志会发现,在 mysql 中,他会按照查询条件先执行一条 count 语句,查询总条数,然后根据用户输入的 pageNum pageSize ,给查询语句拼接一个 limit ?,? ,计算出两个占位符的值。
分页插件的基本原理:使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截
待执行的 sql ,然后重写 sql ,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。

Mybatis如何将sql执行结果封装为目标对象并返回?有哪些映射形式?

第一种:使用标签,逐一定义数据库列名和对象属性名之间的映射关系。
第二种:使用 sql 列的别名功能,将列的别名书写为对象属性名。
有列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

七、常见的动态sql有哪些?

<select>、<insert> 、<update>、 <delete>、<where>、<if> 、<foreach>、<trim> 、<choose><when>、<otherwise>
sqlsession

八、MyBatis实现一对一有几种方式?具体怎么操作的?

两种,联合查询和嵌套查询。
联合查询:几个表联合查询 , 只查询一次 , 通过在 resultMap 里面配置 association节点配置一对一的类就可以完成;
嵌套查询:先查一个表,根据这个表里面的结果的 外键 id ,去再另外一个表里面查询数据 , 也是通过 association配置,但另外一个表的查询通过 select 属性配置。

九、Mybatis延迟加载,及实现原理

介绍:
MyBatis 中的延迟加载( Lazy Loading )是一种优化数据库查询性能的技术。它允许在需要的时候,才去真正加 载关联对象的数据,而不是在初始化查询时就将所有相关数据一次性加载到内存中。延迟加载通常与一对一、多对一、多对多等关联关系结合使用。
比如查看一个商品,需要的时候再展示商品对应的购买评论,大多数情况下用户可能只是看一眼商品信息,只有感兴趣的时候,才会看评论,这个评论就可以使用延迟加载。
实现原理:
MyBatis 中,延迟加载主要是基于代理( Proxy-based )的延迟加载,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName() ,拦截器 invoke() 方法发现a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql ,把 B 查询上来,然后调用 a.setB(b) ,于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName() 方法的调用。

十、Mybatis的缓存机制

Mybatis 有一级缓存和二级缓存
一级缓存:默认开启,使用范围是同一个 sqlSession,多次获取的是同一个对象,
二级缓存:手工开启 EnableCache ,查询条件里也要再开启一次。 可以被多个 sqlSession 共享,他的粒度更细,能到 namespace 级别。 必须要求缓存的对象实现了序列化,所以获取到的对象是反序列化回来的,不是同一个对象。
注意:由于默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis Cache 接口实现,有一定的开发成本,直接使用 Redis Memcached 等分布式缓存可能成本更低,安全性也更高。

十一、JDBC 编程步骤

1. 装载相应的数据库的 JDBC 驱动并进行初始化:
Class . forName ( "com.mysql.jdbc.Driver" );
2. 建立 JDBC 和数据库之间的 Connection 连接:
Connection c = DriverManager . getConnection ( "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8" , "root" , "123456" );
3. 创建 Statement 或者 PreparedStatement 接口,执行 SQL 语句。
4. 处理和显示结果。
5. 释放资源。

十二、MyBatis 常见的设计模式

MyBatis 是一个开源的持久层框架,它在设计中使用了多种设计模式来实现各种功能和提供灵活性。以下是MyBatis 中使用到的一些设计模式:
1. 工厂模式 Factory Pattern
  MyBatis 使用工厂模式来创建和管理 SqlSessionFactory 实例。 SqlSessionFactoryBuilder 作为构建工厂,负责创建 SqlSessionFactory 实例。
2. 建造者模式( Builder Pattern
SqlSessionFactoryBuilder 使用了建造者模式来构建复杂的 SqlSessionFactory 对象。通过链式调用和设置不同的属性来创建配置灵活的 SqlSessionFactory 实例。
3. 单例模式 Singleton Pattern
SqlSessionFactory 往往被设计为单例模式,因为它的创建和初始化过程是相对昂贵的。通过单例模式确保在应用程序的生命周期内只有一个 SqlSessionFactory 实例,提高了性能和资源利用率。
4. 代理模式 Proxy Pattern
MyBatis 中的 Mapper 接口在底层都会被动态代理生成实现类。这些实现类在调用时会执行对应的
SQL 操作。这种代理模式隐藏了底层的实现细节,使得调用方可以像调用本地方法一样调用 Mapper 接口。
5. 模板模式 Template Pattern
MyBatis 中的 SqlSession 类提供了一组用于执行 SQL 操作的模板方法,如 select() insert()
update() delete() 等。这些方法定义了算法的骨架,具体的 SQL 执行细节由不同的子类实现。
6. 观察者模式( Observer Pattern
MyBatis 中的 Interceptor 接口和 InterceptorChain 类实现了观察者模式。 Interceptor 接口定义了拦截器的行为,而 InterceptorChain 则负责管理和调度拦截器,当执行 SQL 操作时,拦截器链会被触发,执行一系列的拦截逻辑。
7. 适配器模式( Adapter Pattern
MyBatis 中的 ResultSetHandler 接口和各种实现类就是适配器模式的应用。 ResultSetHandler 定义了对结果集的处理方法,不同的实现类可以适配不同的处理逻辑,比如DefaultResultSetHandler 、FastResultSetHandler 等。
这些设计模式使得 MyBatis 在实现上具有了高度的灵活性、可扩展性和可维护性,同时也降低了框架的复杂度。

十三、mybatis只写一个接口,没写实现类,为什么还能调用

使用 JDK 动态代理 +MapperProxy 。本质上调用的是 MapperProxy invoke 方法。

十四、springboot是如何集成mybatis的(必会)

1、maven 配置文件中导入 mybatis starter
2、yml 文件中配置 myatis 相关信息 别名 mapper.xml 文件的路径 开启驼峰命名 日志等
3、在 mapper.java 文件上加上 @Mapper 注解,或在全局配置上加上 @MapperScan

十五、MyBatis中的常见注解及作用

@MapperScan、@Mapper、@Select、@Insert、@Update、@Delete、@Param、@Results 和 @Result

@MapperScan: 用于扫描指定包下的 Mapper 接口,并注册到 Spring 容器中。通常配合在 Spring Boot 项目中使用。
@Mapper: 用于标记 Mapper 接口,告诉 MyBatis 这是一个 Mapper 接口,可以被扫描并动态生成实现类。
@Select: 用于配置查询语句,将方法映射到 SQL 查询语句,用于查询操作。
@Insert: 用于配置插入语句,将方法映射到 SQL 插入语句,用于插入操作。
@Update: 用于配置更新语句,将方法映射到 SQL 更新语句,用于更新操作。
@Delete: 用于配置删除语句,将方法映射到 SQL 删除语句,用于删除操作。
@Param: 用于给方法参数取别名,解决方法参数为多个时,SQL 中的参数名称不明确的问题。@Results 和 @Result: 用于配置查询结果映射,将数据库字段映射到 Java 对象的属性。

十六、ResultMapResultType区别

MyBatis 中, ResultMap ResultType 都用于映射查询结果到 Java 对象
ResultType
作用: ResultType 用于指定查询结果的类型,即映射的目标 Java 对象的类型。
使用方式: SQL 映射文件中或者注解方式中,通过 resultType 属性指定返回结果的类型。
eg:
<select id="getUser" resultType="User">
SELECT * FROM users WHERE id = #{userId}
</select>
ResultMap
作用: ResultMap 用于定义复杂的映射规则,将查询结果的列与 Java 对象的属性进行映射。
使用方式: SQL 映射文件中,通过 <resultMap> 元素定义一个结果映射,并在 <select> 中使用 resultMap 属性引用这个映射。
eg:
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name" />
<result property="email" column="user_email" />
</resultMap>
<select id="getUser" resultMap="userResultMap"> SELECT user_id, user_name, user_email FROM users WHERE id = #{userId}
</select>
优势: ResultMap 的主要优势在于它提供了更灵活的映射规则,可以处理数据库表与 Java 对象之间的复杂映射关系,包括关联关系、嵌套查询等。另外 resultMap 还支持 collection associatio
总结: ResultType 用于简单的映射情况,直接指定返回结果的类型;而 ResultMap 则用于处理更复杂的映射,提供了更灵活的配置选项,可以定义详细的映射规则。在实际应用中,根据业务需求和查询复杂度的不同,选择使用 ResultType 或 ResultMap

十七、collectionassociation怎么做一对多和多对一

使用 <collection> 实现一对多:
在父对象(一的一方)的 <resultMap> 中使用 <collection> 元素定义集合属性。
使用 select 属性指定子查询的 SQL 语句。
使用 column 属性指定父对象关联键与子对象关联键的对应关系。
eg:
<resultMap id="parentResultMap" type="Parent">
<id property="parentId" column="parent_id" />
<result property="parentName" column="parent_name" />
<!-- 一对多关系 -->
<collection property="children" ofType="Child" select="getChildByParentId">
<id property="childId" column="child_id" />
<result property="childName" column="child_name" />
</collection>
</resultMap>
<select id="getParents" resultType="Parent">
SELECT * FROM parent;
</select>
<select id="getChildByParentId" parameterType="Long" resultType="Child">
SELECT * FROM child WHERE parent_id = #{parentId}
</select>
使用 <association> 实现多对一:
在子对象(多的一方)的 <resultMap> 中使用 <association> 元素定义关联属性。
使用 select 属性指定父对象查询的 SQL 语句。
使用 column 属性指定父对象关联键与子对象关联键的对应关系。
eg:
<resultMap id="childResultMap" type="Child">
<id property="childId" column="child_id" />
<result property="childName" column="child_name" />
<!-- 多对一关系 -->
<association property="parent" javaType="Parent" select="getParentByChildId">
<id property="parentId" column="parent_id" />
<result property="parentName" column="parent_name" />
</association>
</resultMap> <select id="getChildren" resultType="Child">
SELECT * FROM child;
</select>
<select id="getParentByChildId" parameterType="Long" resultType="Parent">
SELECT * FROM parent WHERE parent_id = #{parentId}
</select>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值