MyBatis框架入门
学习目录:
一、MyBatis是什么
二、第一个MyBatis程序
三、MyBatis三个基本要素
四、MyBatis执行SQL的两种方式
五、MyBatis标签
六、resultMap元素
七、关联(级联)查询
八、动态SQL
九、分页功能
十、缓存(一级缓存和二级缓存)
十一、逆向工程
一、MyBatis是什么
面试官让你一句话概括MyBatis是什么?
MyBatis是一个开源的、轻量级的数据持久化框架。其内部封装了JDBC,简化了加载驱动、创建连接、创建statement等繁杂的中间过程,开发者只需要关注SQL语句本身。
面试官问你为什么要使用MyBatis框架,使用它有什么优点?
1.首当其冲的就是它的免费开源。
2.简化了操作数据库的中间过程,与JDBC相比减少了50%以上的代码量。
3.SQL写在XML文件中,和程序的逻辑代码分离,降低了耦合度,方便SQL同一管理与优化。
4.提供了一些非常方便的SQL标签,支持编写动态SQL。
面试官问,那MyBatis有没有什么缺点呢?
1.不像Hibernate全自动的持久化框架,使用MyBtis框架需要编写大量的SQL语句,而且对开发人员编写SQL语句的功底有一定的要求。
2.编写的SQL语句过于依赖数据库,不同的数据库SQL语句是不一样的,所以项目不能轻易更换数据库,可移植性较差。
二、第一个MyBatis程序
面试官问,编写一个完整的MyBatis程序一共分为哪几步呢?
1.在数据库中建立数据库表。
2.在程序代码中创建数据库表对应的实体类DO。
3.创建xml映射文件,指定xml的namespace,使得数据库表与实体类之间形成对应关系。
4.创建MyBatis的核心配置文件mybatis-config.xml,配置数据源等信息,同时将mapper.xml文件加入到配置文件中。
5.测试,读取mybatis-config.xml配置文件,建造sql工厂,使用这个工厂生成数据库连接对象openSession,调用mapper方法进行测试。
三、MyBatis三个基本要素
1.MyBatis核心接口和类
2.MyBatis核心配置文件 mybatis-config.xml
3.MyBatis Mapper映射器
MyBatis核心接口和类有哪些?
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
仔细讲讲
1.首先根据xml配置文件或者Configuration类的实例构建SqlSessionFactoryBuilder对象。
SqlSessionFactoryBuilder 的最大特点就是用过即丢。创建 SqlSessionFactory 对象之后,这个类就不存在了,因此 SqlSessionFactoryBuilder 的最佳范围就是存在于方法体内,也就是局部变量。
2.通过 SqlSessionFactoryBuilder 对象来构建SqlSessionFactory对象。
SqlSessionFactory 对象一旦创建,就会在整个应用程序过程中始终存在。没有理由去销毁或再创建它,并且在应用程序运行中也不建议多次创建 SqlSessionFactory。因此 SqlSessionFactory 的最佳作用域是 Application,即随着应用程序的生命周期一直存在。这种“存在于整个应用运行期间,并且只存在一个对象实例”的模式就是所谓的单例模式(指在运行期间有且仅有一个实例)。
3.通过SqlSessionFactory 工厂对象,就可以获取 SqlSession 实例。SqlSession 对象中完全包含以数据库为背景的所有执行 SQL 操作的方法,用该实例可以直接执行已映射的 SQL 语句。
SqlSession 对应一次数据库会话。由于数据库会话不是永久的,因此 SqlSession 的生命周期也不是永久的,每次访问数据库时都需要创建 SqlSession 对象。需要注意的是:每个线程都有自己的 SqlSession 实例,SqlSession 实例不能被共享,也不是线程安全的。因此 SqlSession 的作用域范围是 request 作用域或方法体作用域内。
面试官:给我们讲讲MyBatis核心配置文件 mybatis-config.xml
要了解核心配置文件,首先就是要对这个配置文件的结构有个整体的了解
其结构:
<?xml version="1.0" encoding="utf-8"?> DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties /> <settings /> <typeAliases /> <typeHandlers /> <objectFactory /> <plugins /> <environments> <environment> <transactionManager /> <dataSource /> environment> environments> <databaseIdProvider /> <mappers /> configuration>
注意:上面结构的节点位置需要按照顺序设置,否则会报错。
其中常用的标签有哪些?
1.properties标签
用来加载指定的数据库连接信息
<properties resource="resources/db.properties"/>
2.settting标签里面有很多东西,但是一般不需要去主动设置,使用它的默认设置就好。
全量配置样例:
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> settings>
3.typeAliases标签
别名设置标签,设置了类的别名,在使用的时候就直接使用别名就好了,不需要每次都写全限定类名了。
<typeAliases> <typeAlias alias = "student" type = "xxx.xx.xx.Student"/> typeAliases>
当然当类的数量太多了时,并不需要一个一个去设置,直接扫描整个包进行别名设置就好,别名就是类名的第一个字母小写。
<typeAliases> <package name="xxx.xxx.po"/> typeAliases>
4.environments标签
配置 MyBatis 的多套运行环境
5.transactionManager标签
MyBatis 支持两个事务管理器,即 JDBC 和 MANAGED。
如果使用 JDBC 类型的事务管理器,则应用程序服务器负责事务管理操作,例如提交、回滚等。如果使用 MANAGED 类型的事务管理器,则应用程序服务器负责管理连接生命周期。
6.dataSource标签
配置连接数据库的信息
type 属性用于指定数据源类型
1)UNPOOLED
UNPOOLED 没有数据库连接池,效率低下。MyBatis 需要打开和关闭每个数据库操作的连接,它有点慢,通常应用于简单的应用程序。
2)POOLED
对于 POOLED 数据源类型,MyBatis 将维护一个数据库连接池。并且对于每个数据库的操作,MyBatis 都会使用连接池中的连接,并在操作完成后将它们返回到池中。减少了创建新连接所需的初始连接和身份验证时间。
3)JNDI
对于 JNDI 的数据源类型,MyBatis 将从 JNDI 数据源中获取连接。
<dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="root" /> dataSource>
7.mapper标签
用于指定 MyBatis SQL 映射文件的路径
<mappers> <mapper resource="xxx/xxx/mapper/Student.xml"/> mappers>
同样,这里也可以用扫描整个包的方式,全部加入进来。
面试官:介绍一下MyBatis Mapper映射器
映射器是 MyBatis 中最重要的文件,文件中包含一组 SQL 语句(例如查询、添加、删除、修改),这些语句称为映射语句或映射 SQL 语句。
映射器由 Java 接口(mapper)和 XML 文件(或注解)共同组成。一一对应共同组成MyBatis映射器。
映射器的两种实现方式:
1.通过 XML 文件方式实现,比如我们在 mybatis-config.xml 文件中描述的 XML 文件,用来生成 mapper。
2.通过注解的方式实现,使用 Configuration 对象注册 Mapper 接口。即直接在Mapper接口里面的方法上直接使用注解形成映射器。
四、MyBatis执行SQL的两种方式
1.直接一步到位,通过 SqlSession 发送 指定的SQL语句。
示例:
Student student = (Student)sqlSession.selectOne("xxx.xxx.mapper.xxxMapper.getStudent",1);
通过操作数据库的对象sqlSession,明确指定需要指定的SQL语句和传递的参数。
2.分两步,中间借助mapper接口过度,通过 SqlSession 获取 Mapper 接口,通过 Mapper 接口发送 SQL。
示例:
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student student = studentMapper.getStudent(1);
建议使用第二种
使用 Mapper 接口编程可以消除 SqlSession 带来的功能性代码,提高可读性。同时,使用第二种方式IDE会在编码是提示错误和校验,而第一种语法方式,只有在运行中才能知道是否会产生错误。
五、MyBatis标签
select标签
insert标签
update标签
delete标签
标签的常用属性
id 绑定接口方法
parameterType 传递进来的参数类型
resultType 返回的参数类型
resultMap 实体类属性与数据库字段的映射
传递参数的方式
1.使用注解进行传参。
2.使用Map进行传参。
3.使用JavaBean进行传参。
三种传参方式的区别:
使用 Map 传递参数会导致业务可读性的丧失,继而导致后续扩展和维护的困难,所以在实际应用中我们应该果断废弃该方式。使用 @Param 注解传递参数会受到参数个数的影响。当 n≤5 时,它是最佳的传参方式,因为它更加直观;当 n>5 时,多个参数将给调用带来困难。
当参数个数大于 5 个时,建议使用 JavaBean 方式。
六、resultMap元素
MyBatis中最复杂的元素,主要用于解决实体类属性名与数据库表中字段名不一致的情况,可以将查询结果映射成实体对象。
结构:
<resultMap id="" type=""> <constructor> <idArg/> <arg/> constructor> <id/> <result/> <association property=""/> <collection property=""/> <discriminator javaType=""> <case value=""/> discriminator> resultMap>
resultType与resultMap的区别:
本质上,MyBatis的每一个查询映射的返回类型都是resultMap,只是当我们提供的返回类型是 resultType时,MyBatis会自动把对应的值赋给resultType所指定对象的属性,而当我们提供的返回类型是resultMap时,MyBatis会将数据库中的列数据复制到对象的相应属性上,可用于复制查询。
七、关联(级联)查询
一对一级联:
通过
两种实现方式:
1.分步查询,通过两次或多次查询,为一对一关系的实体 Bean 赋值。
2.单步查询,通过关联查询实现。
一对多级联:
通过
两种实现方式:
1.分步查询,通过两次或多次查询,为一对一关系的实体 Bean 赋值。
2.单步查询,通过关联查询实现。
多对多级联:
MyBatis 没有实现多对多级联,推荐通过两个一对多级联替换多对多级联,以降低关系的复杂度,简化程序。
例如,一个订单可以有多种商品,一种商品可以对应多个订单,订单与商品就是多对多的级联关系。可以使用一个中间表(订单记录表)将多对多级联转换成两个一对多的关系。
借助一张中间表声明两者之间的关系,如:order(订单),product(商品)和 order_details(订单和商品中间表)。
级联的优点是获取关联数据十分便捷。但是级联过多会增加系统的复杂度,同时降低系统的性能,此增彼减。所以记录超过 3 层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合、负载和难以维护。
八、动态SQL
if标签:条件判断
<if test="判断条件"> SQL语句 if>
choose、when和otherwise标签
choose 标签按顺序判断其内部 when 标签中的判断条件是否成立,如果有一个成立,则执行相应的 SQL 语句,choose 执行结束;如果都不成立,则执行 otherwise 中的 SQL 语句。这类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
<choose> <when test="判断条件1"> SQL语句1 when > <when test="判断条件2"> SQL语句2 when > <when test="判断条件3"> SQL语句3 when > <otherwise> SQL语句4 otherwise> choose>
where标签
用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件。
if 语句中判断条件为 true 时,where 关键字才会加入到组装的 SQL 里面,否则就不加入。where 会检索语句,它会将 where 后的第一个 SQL 条件语句的 AND 或者 OR 关键词去掉。
<where> <if test="判断条件"> AND/OR ... if> where>
set标签
set 标签可以为 SQL 语句动态的添加 set 关键字,剔除追加到条件末尾多余的逗号
<update id="updateStudent" parameterType="xxx.xxx.po.Student"> UPDATE website <set> <if test="name!=null">name=#{name}if> <if test="age!=null">age=#{age}if> set> WHERE id=#{id} update>
foreach标签
<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")"> 参数值 foreach>item:表示集合中每一个元素进行迭代时的别名。
index:指定一个名字,表示在迭代过程中每次迭代到的位置。
open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。
bind标签
数据库的拼接函数或连接符号
<select id="selectStudent" resultType="xxx.xxx.po.Student"> <bind name="pattern" value="'%'+_parameter+'%'" /> SELECT id,name,sex,age,country FROM student WHERE name like #{pattern} select>
trim标签
一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作。
<trim prefix="前缀" suffix="后缀" prefixOverrides="忽略前缀字符" suffixOverrides="忽略后缀字符"> SQL语句 trim>
九、分页功能
前端传入起始位置与页面容量参数。
limit #{from},#{pageSize}
起始位置下标=(页码-1)*页面容量。
十、缓存(一级缓存和二级缓存)
MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存。
一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。
二级缓存是全局缓存,作用域超出 session 范围之外,可以被所有 SqlSession 共享。一级缓存缓存的是 SQL 语句,二级缓存缓存的是结果对象。
十一、逆向工程
这里不做赘述,在mybatis-plus有更好的方式。