什么是MyBatis?
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
相关概念解析:
持久层:持久层就是可以将业务数据存储到磁盘(数据库),具备长期的存储能力。
MyBatis的优势:
灵活!!!同时提供了接口编程!!!目前MyBatis的数据访问层DAO(Data Access Objects)是不需要实现类的,它只需要一个接口和XML(或注解)。
灵活 – 提供自动映射、动态SQL、级联、缓存、注解、SQL分离等。
因为其封装少、映射多样化、支持存储过程、可以进行SQL优化等特点,取代了Hibernate。
Hibernate 与 Mybatis:
POJO对象 – 数据库表 相互映射的框架称为对象关系映射ORM (Object Relational Mapping)。所以说: Hibernate 与 Mybatis 都可以称为 ORM 框架。
但是不同的是: Hibernate的设计理念是完全面向POJO的,不需要编写SQL就可以通过映射关系来操作数据库 – 全表映射 。 而MyBatis则不同,虽然映射…但是它需要提供SQL去运行。这样可以更加精确地定义SQL,从而优化性能,它更符合目前移动互联网高并发、大数据、高性能、高响应的要求。
MyBatis三大特点:
- 不屏蔽SQL – 精确定位,优化,改造
- 映射机制,方便Java开发者使用 – 动态SQL
- 使用Mapper的接口编程,只要一个接口和一个XML就能创建映射器
MyBatis 的核心组件:
SqlSessionFactoryBuilder : 构造器。 他会根据配置或者代码来生成SqlSessionFactory,采用的是分布构造的Builder模式。
SqlSessionFactory : 工厂接口。依靠它来生成SqlSession,使用的是工to厂模式。
SqlSession : 会话。既可以发送SQL执行返回结果,也可以获取Mapper接口。使用MyBatis提供的SQL Mapper接口编程技术,能提高代码的可读性和可维护性。
SQL Mapper:映射器。由一个JAVA接口和XML文件或注解构成,需要给出对应的SQL和映射规则。他负责发送SQL去执行,并返回结果。
核心组件的关系:
总体流程:
(1)加载配置并初始化
触发条件:加载配置文件
处理过程:将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
(2)接收调用请求
触发条件:调用Mybatis提供的API
传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。
(3)处理操作请求
触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象
处理过程:
(A)根据SQL的ID查找对应的MappedStatement对象。
(B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
(C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(E)释放连接资源。
(4)返回处理结果将最终的处理结果返回。
SQL执行的过程:
动态SQL:
如果只使用JDBC或者类似于Hibernate的其它框架,很多时候要根据需要去拼装SQL,……麻烦的一匹。因为需要大量的Java代码进行判断,可读性差。
而MyBatis提供了对SQL语句动态的组装能力,使用XML的几个简单元素,便能完成动态SQL的功能。
举例:
If:
<if test="typeId != null">
AND cargo_type_id = #{typeId}
</if>
当参数typeId 传递进映射器时,如果参数不为空,则采取构造对typeId进行模糊查询,否则就不去构造这个条件。显然这样的场景在实际工作中十分常见,通过MyBatis的if元素节省了许多拼接SQL的工作,集中在XML里面维护。
trim:
<select id="getCargoAttrs" resultType="cargoattr" parameterType="cargoattr"> SELECT cargo_type_id AS typeId, cargo_name AS name, maximum AS maximumInAContainer, unit_type AS unitType FROM cargo_attr_table <trim prefix="WHERE" prefixOverrides="AND"> <if test="typeId != null"> AND cargo_type_id = #{typeId} </if> <if test="name != null"> AND cargo_name = #{name} </if> <if test="maximumInAContainer != null"> AND maximum = #{maximumInAContainer} </if> <if test="unitType != null"> AND unit_type = #{unitType} </if> </trim> </select>
其中prefix 代表的时语句前缀,prefixOverrides代表的是需要去掉的字符串。