秋招Day18 - MyBatis - 基础

发布于:2025-07-25 ⋅ 阅读:(14) ⋅ 点赞:(0)

什么是MyBatis?

MyBatis是一个半ORM框架,它封装了JDBC,开发时只需关注SQL语句本身,不必再编写加载驱动、创建连接、编写statement的繁琐过程。程序员直接编写原生SQL,可以严格控制SQL语句的执行性能,灵活性高

MyBatis可以通过XML和注解的形式来配置映射信息,避免了编写JDBC代码手动处理结果集映射。

缺点是编写SQL语句工作量大,并且SQL语句依赖于数据库,导致不能随意更换数据库

ORM是什么? 

ORM是对象关系映射,就是将程序中的对象映射为数据库中的记录,程序中的对象可以自动持久化到数据库中,数据库中的记录也能自动映射为对象,无需手动逐个处理映射关系。 

为什么说MyBatis是半自动ORM框架,和全自动的区别是什么?

  • Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
  • 而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 SQL 来完成,所以,被称之为半自动 ORM 映射工具。

JDBC编程有哪些不足之处?MyBatis是如何解决的?

  • 1、数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,在 mybatis-config.xml 中配置数据连接池,使用连接池统一管理数据库连接
  • 2、sql 语句写在代码中造成代码不易维护,将 sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离
  • 3、向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数一一对应。Mybatis 自动将 java 对象映射为 sql 语句的参数,灵活处理参数映射。
  • 4、对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。Mybatis 自动将 sql 执行结果映射至 java 对象

Hibernate和MyBatis的区别?

都是对JDBC的封装,都是作用于持久层的框架

不同点:

从映射关系上来看,MyBatis是半自动ORM框架,配置的是Java对象和sql执行结果的映射关系多表关联关系配置简单;Hibernate是全自动ORM框架,配置的是Java对象和数据库全表的对应关系,多表关联关系配置复杂

从SQL优化和移植性角度,MyBatis需要手动编写SQL,可以直接使用SQL语句操作数据库,SQL优化容易,但是数据库可移植性差;Hibernate会自动生成SQL,不用手动编写SQL所以SQL优化困难,但是支持多种数据库

MyBatis使用过程?生命周期?

 

MyBatis生命周期 

MyBatis的生命周期其实就是由各个组件的生命周期组成的

SqlSessionFactoryBulider:一般是临时的,用完即弃,生命周期是方法级的

SqlSessionFactory:复用的连接池,生命周期一般是应用级的,并且是单例的

SqlSession:一次查询会话,生命周期一般是方法级或者事务级别的,线程不安全,不能被共享

Mapper:一次SQL查询,生命周期一般是方法级别的 

在Mapper中如何传递多个参数

方法 1:@Param 注解传参法

public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>
  • \#{}里面的名称对应的是注解@Param 括号里面修饰的名称。
  • 这种方法在参数不多的情况还是比较直观的,(推荐使用)。

方法 2:Map 传参法

public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>
  • \#{}里面的名称对应的是 Map 里面的 key 名称。
  • 这种方法适合传递多个参数,且参数易变能灵活传递的情况。

方法 3:Java Bean 传参法

public User selectUser(User user);

<select id="selectUser" parameterType="com.jourwon.pojo.User" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>
  • \#{}里面的名称对应的是 User 类里面的成员属性。
  • 这种方法直观,需要建一个实体类,扩展不容易,需要加属性,但代码可读性强,业务逻辑处理方便,推荐使用。(推荐使用)。

实体类属性名和表中字段名不一样怎么办?

在查询的SQL语句中自定义数据库字段的别名,使其和实体类属性名一致。

通过 resultMap 中的<result>来映射字段名和实体类属性名的一一对应的关系。

MyBatis是否可以映射Enum枚举类?

可以,需要自定义一个TypeHandler,实现 setParameter() getResult()两个方法,对应javaType到jdbcType设置参数和jdbcType到javaType获取查询结果

#{}和${}的区别?

#{} 是预编译处理${} 是字符串替换

①、当使用 #{} 时,MyBatis 会在 SQL 执行之前,将占位符替换为问号 ?,并使用参数值来替代这些问号。

由于 #{} 使用了预处理,所以能有效防止 SQL 注入,确保参数值在到达数据库之前被正确地处理和转义。

②、当使用 ${} 时,参数的值会直接替换到 SQL 语句中去,而不会经过预处理。

这就存在 SQL 注入的风险,因为参数值会直接拼接到 SQL 语句中,假如参数值是 1 or 1=1,那么 SQL 语句就会变成 SELECT * FROM users WHERE id = 1 or 1=1,这样就会导致查询出所有用户的结果。

${} 通常用于那些不能使用预处理的场合,比如说动态表名、列名、排序等,要提前对参数进行安全性校验。

模糊查询like语句怎么写?

MyBatis能执行一对一、一对多的关联查询吗? 

可以,一对一需要在resultMap中定义association标签,映射关联对象到主对象;一对多需要在resultMap中定义collection标签,映射关联对象集合到主对象

MyBatis是否支持延迟加载?原理?

  • Mybatis 支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。
  • 原理是使用CGLIB创建目标对象的代理对象,当访问这个代理对象的关联对象时,进入拦截器方法intercept(),发现关联对象的值是null未填充,此时会执行查询对应关联对象的sql,然后在set到主对象中,接着完成针对关联对象的获取。

如何获取生成的主键?

xml中的insert标签中添加:keyProperty=" ID " 即可,生成的主键ID会返回设置到对象中

MyBatis支持动态SQL吗?

支持,根据表达式的值动态拼接SQL,比如if标签、choose (when, otherwise)标签,<where>可以用在所有的查询条件都是动态的情况,foreach构建IN语句

MyBatis如何进行批量操作?

foreach构建子句,collection代表集合类型的参数名(单个List或Array类型的参数名直接用list或array,Map类型传入多个参数的话,collection的参数名是map中对应集合的key),item代表每个元素名(随便起),separator 表示在每次进行迭代之间以什么符号作为分隔符,常用“,”;

第二种方法是使用 ExecutorType.BATCH

设置SqlSeesion的模式为BATCH,for循环像平时一样调用 Mapper 接口的方法,实际每次调用都不会立即执行而是缓存累积SQL语句,按照一定的频率批量提交累计的SQL语句 

说说MyBatis的一级、二级缓存?

一级缓存:作用域是sqlSession,各个sqlSession之间的一级缓存是隔离的,基于HashMap,默认开启,可以减少重复数据库查询

二级缓存:作用域是Mapper,各个sqlSession之间共享,也是基于HashMap,需要手动打开,实现SqlSession 的数据共享进一步减少数据库查询


网站公告

今日签到

点亮在社区的每一天
去签到