一、MyBatis和jdbc的区别
jdbc的过程包括:
1、加载数据库驱动。
2、建立数据库连接。
3、编写sql语句。
4、获取Statement:(Statement、PrepareStatement、callableStatement)。
5、执行executionQuery。
6、获取ResultSet结果集。
7、处理ResultSet结果集。
6、关闭资源:rs,Statement,conn。
MyBatis工作流程
1、加载配置并初始化
触发条件:加载配置文件
配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
MyBatis将一次sql会话抽象为一个SqlSession对象,对象通过SqlSessionFactory.openSqlSession()获取,一个SqlSesion表示一次会话。处理内容为:向SQL传入参数、执行SQL语句、获取执行SQL语句的结果、事务控制。
2、接收调用请求
触发条件:调用Mybatis提供的API
传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。
3、处理操作请求
触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象
处理过程:
(A)根据SQL的ID查找对应的MappedStatement对象。
(B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
(C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(E)释放连接资源。
4、返回处理结果将最终的处理结果返回。
简单来说就是,controler->service->service调用相关方法到mapper(传递参数1 SQL-ID 2 传入参数对象 到MappedStatement对象)mapper执行ID对应的SQL语句并将结果返回到数据库映射的对象的集合中去。
二、MyBatis做的优化。
1:使用连接池,datasource,在驱动并连接的这个过程中优化并解耦
JDBC第一步其实从效率角度来
看是不合适的,因为无论什么数据库都不可能支撑随机和庞大的连接数,而且不可避免的存在连接浪费的情况,Mybatis就封装了这些优化的方法。
2:统一sql存取到XML
如果代码写在java块中,在团队合作中很可能出现两个交叉业务的代码使用类似的sql语句,而开发人员的工作本身没有交集,那就代表sql语句肯定是无法复用的。而且对sql的修改,就代表着
对java文件的修改,需要重新编译和打包部署(比如常见的状态值更改,sql修改随着业务变化必然存在修改)。
mybatis将sql统一存取到xml中,就算存在业务交叉,但因为统一配置的缘故,sql在xml中一目了然,两个跨team的程序员可以看到对方的sql,来判断自己是否需要重用。并且使用xml配置可以减少代码编译。
3:参数和结果集映射
sql的方式需要传入参数,如果存在多条件“或类型”的查询(列表查询的查询条件允许空),那就代表你必须传参进行sql拼接,就算使用xml的方式也不行。要么每个业务独立配置xml中的sql,要么还是写入java代码中,或者以工具的方式进行自动拼接。
Mybatis使用映射的方式,方便model管理参数,同时以解析器的方式将参数动态拼接到sql(sqlmaper里那些标签),由于是model映射,连查询结果都可以统一映射,方便取出和运算。而且mybatis对查询结果集进行了缓存处理,使得重复查询进一步进行了优化。
4:对多重复sql进行复用封装
比如模板方法,将常用sql模块化,直接调用。比如通用的save和getID之类的,只有表名和字段名有变化。
三、MyBatis全局配置文件的配置
四、MyBatis映射文件配置
五、OGNL表达式与动态SQL配置
常用的Mybatis动态sql标签有6种:
1. if 语句 (简单的条件判断)
2. choose (when,otherwize) ,相当于Java 语言中的 switch ,与 jstl 中的choose 很类似.
3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)
5. set (主要用于更新时)
6. foreach (在实现 mybatis in 语句查询时特别有用)
(1) if
模糊查询
<select id="select1" resultType="BaseresultMap">
SELECT * FROM User WHERE Age = ‘18'
<if test="name != null">
AND name like #{name}
</if>
6 </select>
年龄18且可以模糊搜索姓名
(2)choose,when,otherwize
当Job参数有传入时,就找出对应工作的人,否则就找出Job为none的人,而不是所有人
<select id="select2" resultType="BaseresultMap">
SELECT * FROM User WHERE Age = ‘18' <choose>
<when test="Job != null">
AND Job =#{Job}
</when>
<otherwise>
AND Job="none" </otherwise>
</choose>
</select>
(3)foreach
<select id="select5" resultType="BaseresultBase">
select * from User where id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
public List<User> select5(List<Integer> ids);
(4)where,set
为什么要用where,因为单纯的写where可能会导致 where And ... 和 where .....情况的发生,Set也是一样的
当然 trim 标签是万能的
<select id="select3" resultType="BaseresultMap">
SELECT * FROM User
<where>
5 <if test="Age != null">
Age = #{Age}
</if>
<if test="Job != null">
AND Job like #{Job}
</if>
<where>
</select>
<update id="update1">
update User
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="Age != null">Age =#{Age}</if>
</set>
where id=#{id}
</update>