目录
1.什么是MyBatis
2.MyBatis优缺点
3.MyBatis工作原理
4.MyBatis缓存模式
5.MyBatis代码相关问题
6.MyBatis和hibernate区别
1.什么是MyBatis
MyBatis是一个半ORM持久层框架(对象关系映射),基于JDBC进行封装,使得开发者可以专注于SQL语句,不用关系JDBC操作的流程。
MyBatis支持定制化 、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOS(Plain Ordinary Java Object,普通的 Java对象,即实际开发中的实体类)映射成数据库中的记录。
2.MyBatis优缺点
MyBatis作为市面上应用最为广泛的数据库框架,具有以下优点:
-
简单易学:本身就很小且简单。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
-
灵活便捷:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。同时,减少了JDBC相关代码,大大减少了代码量。
-
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
-
兼容性好:基于JDBC进行封装,所以可以和很多数据库兼容。
-
提供xml标签,支持编写动态sql。
但同时,MyBatis也还具有一定的缺点:
- SQL语句编程量较大,较为考验使用者的SQL功力。
- SQL语句与具体数据库依赖很大,使得数据库移植性差。
3.MyBatis工作原理
MyBatis的工作原理主要依赖于SqlSessionFactory和SqlSession两大类。其主要分为两大过程:
(1)MyBatis启动加载。Mybatis会获取一个SqlSessionFactory对象,完成全局配置文件和映射文件的加载解析操作,然后把相关信息保存到Configuration对象中。然后通过SqlSessionFactory获取SqlSession对象(基于DefaultSqlSessio对象实现)。
SqlSessionFactory类,它是单个数据库映射关系经过编译后的内存镜像,主要是创建DefaultSqlSessionFactory对象进行具体实现。而SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来获得,而SqlSessionFactoryBuildr则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
(2)MyBatis处理请求。SqlSession类中提供了处理请求的方法(select、update等),并调用对应的Executor处理。处理过程中,如果有配置缓存,先走二级缓存,再走一级缓存,缓存不命中,再走数据库操作。会通过StatementHandler处理,先通过ParameterHandler处理SQL中的占位符,再通过ResultSetHandler处理结果集的映射。
SqlSession类,同理,主要是创建DefaultSqlSession对象进行具体实现。SqlSession接口实例执行方法的过程中主要会去执行Executor类的方法,进行请求的具体处理。
总结来说,具体的工作流程就是通过SqlSessionFactoryBuilder从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例,再由SqlSessionFactory创建出一个SqlSession,并由该SqlSession进行请求的处理,执行事务和SQL语句。
4.MyBatis缓存模式
mybatis为减轻数据库压力,提高数据库性能,提供了两级缓存机制:
(1)一级缓存:
基于会话(session)的缓存。一级缓存是默认放开的,但需开启事务进行使用(就是同一个事务中的第二次查询会走缓存)。MyBatis中一级缓存也叫做本地缓存,于SqlSession层面实现的,所以作用范围是在同一个SqlSession中,不同的SqlSession及时查询相同的数据也不会走缓存。
(2)二级缓存:
基于进程(使用装饰器维护,涉及到了装饰器模式,需要了解可参考java设计模式——装饰器模式)的缓存。MyBatis中二级缓存的作用域是namespace(命名空间),所以很显然二级缓存是需要存储在SqlSession之外的:
二级缓存缓存范围比一级缓存更大,不同的SQLSession可以访问二级缓存的内容,所以二级缓存需要自己开启,哪些数据放入二级缓存需要自己指定。
开启方式(application.yml文件配置):
# mybatis相关配置
mybatis:
configuration:
#开启MyBatis的二级缓存
cache-enabled: true
或是在mapper.xml文件中添加代码:
其中eviction属性指缓存回收策略,flushInterval则是缓存更新时间(上述代码中为1分钟)
eviction:缓存的回收策略,默认的是 LRU。
- LRU - 最近最少使用,移除最长时间不被使用的对象。
- FIFO - 先进先出,按对象进入缓存的顺序来移除它们。
- SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象。
- WEAK - 弱引用,更积极地移除基于垃圾收集器和弱引用规则的对象。
(3)三级缓存:
三级缓存又称为自定义缓存,如使用Redis进行缓存等,需要自行进行配置操作。
实际代码中如何开启
5.MyBatis代码相关问题
(1)获取自增主键:如果数据库中设计了主键id自动增长,那么可以通过MyBatis中的mapper.xml文件中的属性配置,获取该值,并进行插入:
<insert id="addEmployee" parameterType="employee" useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee (id, name, email, gender)
values (#{id}, #{name}, #{email}, #{gender});
</insert>
核心代码为: useGeneratedKeys="true" keyProperty="id"
(2)属性名和字段名不一致:主要通过resultMap标签处理。
<resultMap id="empResultMap" type="Emp">
<id column="student_id" property="id"></id>
<result column="s_name" property="name"></result>
</resultMap>
<select resultMap="empResultMap">
select * from student where student_id = #{id}
</select>
(3)#和$的区别:
- #{}是预编译处理,会把传入的数据都当成一个字符串来处理,所以会在传入的数据上面加一个双引号。其在mybatis处理时替换为?,然后进行赋值。
- ${}是在mybatis处理时直接替换,作用相等于是字符串拼接,所以会有SQL注入风险。
例子:
select * from student where name= #{name}
上述语句中,该sql语句会将#{name}替换为?,然后获取到传入的@Param的参数值时(比如name="seven"),再传入(整个"seven"进行传入)。
select * from student where name= ${name}
如果传入的name类型为整型类型,那么在执行sql语句时就不会出错,但是如果传入的name类型为字符串型,就会变成select * from student where name=seven,执行会报错。
所以,一般情况下,传入参数使用 #{},如果需要凭借SQL语句时,才使用${}。
6.MyBatis和hibernate区别
Hibernate也是一个对象关系映射框架,同样基于JDBC进行封装,工作原理与MyBatis类似。其余MyBatis之间主要区别如下:
MyBatis | Hibernate |
半自动框架,需要手动编写SQL语句 | 全自动的orm框架,hibernate可以自动生成SQL语句,自动执行 |
日志模块只有基本记录功能 | 拥有完成的日志系统 |
缓存模块需要在每个表-对象进行详细配置 | 缓存机制上更优 |
移植性较差 | 移植性更强 |
由于sql都是手动编写,且存于xml文件中,优化更为便捷 | 由于sql都是自动生成,优化较为困难,且遇到一些较为复杂的sql操作时,无法达成目的。 |
总结来说,mybatis较为轻便简单,而直接使用sql语句,开发更方便,上手更快。Hibernate框架更为复杂,也更加严谨。