1. MyBatis基本工作原理介绍
[MyBatis的基本工作原理就是]:
先封装SQL,接着调用JDBC操作数据库,最后把数据库返回的表结果封装成Java类。
[作用]:
Mybatis框架解决了数据库编程相关的问题,主要是简化了数据库编程。
当使用Mybatis框架实现数据库编程时,只需要:
- 定义数据操作功能的抽象方法(此抽象方法必须在接口中)
- 配置以上抽象方法映射的SQL语句
[特殊]
计算机的基本工作就是存储和计算,而MyBatis是存储领域的利器。
2. MyBatis的核心流程介绍
[]简写步骤]
- 1.mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件中构建出SqlSessionFactory
- 2.后通过SqlSessionFactory的实例直接开启一个SqlSession(创建会话对象)
- 3.通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,
- 4.关闭SqlSession。
[详写步骤]
- /**上面中流程就是MyBatis内部核心流程,每一步流程的详细说明如下文所述:*/(最下方流程图)
- (1)读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。
- (2)加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
- (3)构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。
- (4)创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
- /**通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交*/
- (5)Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
- (6)MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
- (7)输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
- (8)输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。
MyBatis四大核心+JDBC有四个核心对象
JDBC有四个核心对象:
(1)DriverManager,用于注册数据库连接
(2)Connection,与数据库连接对象
(3)Statement/PrepareStatement,操作数据库SQL语句的对象
(4)ResultSet,结果集或一张虚拟表
MyBatis也有四大核心对象:
(1)SqlSession对象,该对象中包含了执行SQL语句的所有方法【1】。类似于JDBC里面的Connection 【2】。
(2)Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
(3)MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
(4)ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回
[图解]
3.MyBatis常用注解
@MapperScan :后跟路径指向mapper包,对mapper包进行扫描, ,与@Configuration(配置类连用)连用,作用是可以不用在每个接口上都加@Mapper注解了
@Mapper :在接口类上添加了@Mapper
@Repository
@Param :参数标签
@Insert @Delete @Update @Select(不使用 .xml文件 写SQL语句时使用) (具体用法放在mapper接口中的抽象方法上使用)
4.常用关键字
/**id="insert" id等于的是mapper中抽象方法的方法名*/
<insert id="insert" useGeneratedKeys="true" keyProperty="id"></insert> //配置自增id写法
/**封装字段*/
<include refid="DetailQueryFields" />
<sql id="DetailQueryFields">
<if test="true">
//此处存放字段名用,隔开写多个
</if>
</sql>
ResultMap,ResultType 区别
/**ResultMap,ResultType 区别*/
基本映射 :(resultType)使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。(数据库,实体,查询字段,这些全部都得一一对应)高级映射 :(resultMap) 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。(高级映射,字段名称可以不一致,通过映射来实现
resultType和resultMap功能类似 ,都是返回对象信息 ,但是resultMap要更强大一些 ,可自定义。
因为resultMap要配置一下,表和类的一一对应关系,所以说就算你的字段名和你的实体类的属性名不一样也没关系,都会给你映射出来
------------------------------------------------
<select id="count" resultType="int"> </select>
<select id="count" resultType="cn.tedu.csmall.server.pojo.vo.AlbumListItemVO"> </select>
<select id="getById" resultMap="DetailResultMap"></select>
<resultMap id="ListItemResultMap" type="cn.tedu.csmall.server.pojo.vo.AlbumListItemVO">
<id column="id" property="id"/>
<result column="product_count" property="productCount" />
</resultMap>
-----------------------------------------------------
/**当外部传入List时怎么处理 遍历集合*/
<foreach collection="array" item="id" separator=",">#{id}</foreach>
[此例子为得到自动编号的ID值]
另外,在插入数据时,还可以配置,得到自动编号的ID值,具体做法是在<insert>节点上添加配置:
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
暂不关心此处的SQL语句
</insert>
6.关于此文件的配置(两个地方)
/**关于.xml此文件的内部配置:*/
1.根节名必须是<mapper>
2.根节点必须配置namespace属性,取值为对应的接口的全限定名
(例子:<mapper namespace="cn.tedu.csmall.server.mapper.AlbumMapper">)
3.在根节点内部,根据需要执行的SQL语句的类型不同,使用<insert>、<delete>、<update>、<select>节点
4.在<insert id="">等节点上,必须配置id属性,取值为抽象方法的名称(不包含括号及参数)
5.在<insert><insert/>等节点内部,配置SQL语句,SQL语句不需要使用分号结束
/**在application.properties类中的数据配置*/
1.[此例子为配置.xml文件所在位置]
需要补充一个配置,用于告诉Mybatis框架.xml文件的位置!在application.properties中添加:
mybatis.mapper-locations=classpath:mapper/*.xml
(/**的意思是所有文件夹及里面的子文件夹
/*是所有文件夹,不含子文件夹
/是web项目的根目录)
2.[配置连接数据库的参数]
//数据库端口号+数据库名字+统一编码+utf-8编码+时区
spring.datasource.url=jdbc:mysql://localhost:3306/mall_pms?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
//接通数据库时的用户名+密码
spring.datasource.username=root
spring.datasource.password=root */
特殊3.[Spring Boot在application.properties类中配置,服务端口(默认8080)]
server.port=8080
3.[此例子为得到自动编号的ID值]
另外,在插入数据时,还可以配置,得到自动编号的ID值,具体做法是在<insert>节点上添加配置:
<!-- int insert(Brand brand); -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
暂不关心此处的SQL语句
</insert>
7. Mybatis实现动态SQL的修改数据(if,null)(<foreach遍历集合 >)
/**Mybatis实现动态SQL的修改数据*/
1). 在动态SQL机制中,可以使用`<if>`标签,可用于对某参数值进行判断,从而生成不同的SQL语句片段,常用于设计更新数据的操作。
目标:使用1个方法,实现多种不同的数据更新(想更新哪些字段就更新哪些字段,不想更新的字段值将保持不变)
需要执行的SQL语句大致是:
update pms_brand set name=?, pinyin=?, logo=? where id=?
2). 注意:以上SQL语句的修改的字段列表应该不是固定的,应该根据传入的参数值来决定 ,
先在BrandMapper接口中添加抽象方法:int updateById(Brand brand);
然后,在BrandMapper.xml中进行配置:
<!-- int updateById(Brand brand); -->
<update id="updateById">
UPDATE
pms_brand
<set>
<if test="name != null">
name=#{name},
</if>
<if test="pinyin != null">
pinyin=#{pinyin},
</if>
<if test="logo != null">
logo=#{logo},
</if>
</set>
WHERE
id=#{id}
</update>
1). 需要注意的是,在Mybatis的动态SQL中,<if>并没有对应的<else>,如果一定要实现类似Java中的if...else效果,需要使用<choose>标签,其基本格式是:
<choose>
<when test="条件">
满足条件时的SQL片段
</when>
<otherwise>
不满足条件时的SQL片段
</otherwise>
</choose>
2). 或者,也可以使用2个条件完全相反的<if>标签来实现类似效果(但是执行效率偏低),例如:
<if test="pinyin != null">
某代码片段
</if>
<if test="pinyin == null">
某代码片段
</if>
遍历传入的集合数据的id,根据id挨个删除每条数据
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
例子: 遍历传入的集合数据的id,根据id挨个删除每条数据
<delete id="deleteByIds">
DELETE
FROM
pms_brand
WHERE
id IN (
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</delete>