文章目录
JDBC的不足之处 & MyBatis的解决方案
- 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能。
- 解决方案:在
mybatis-config.xml
中配置数据连接池,使用连接池管理数据库连接。
- 解决方案:在
- Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
- 解决方案:将Sql语句配置在
XXXXmapper.xml
文件中与java代码分离开。
- 解决方案:将Sql语句配置在
- 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
- 解决方案:Mybatis自动将java对象映射至sql语句。
- 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历。
- 解决方案:Mybatis自动将sql执行结果映射至java对象。
MyBatis中Dao接口和XML文件的SQL如何建立关联
- MyBatis会把每个SQL标签封装成SqlSource对象,XML文件中的每一个SQL标签就对应一个MappedStatement对象,其中有两个属性非常重要:
- id:全限定类名+方法名组成的ID。
- sqlSource:当前SQL标签对应的SqlSource对象。
- Dao接口的工作原理是JDK动态代理,MyBatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
- Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement
举个栗子:
接口方法:com.mybatis3.mappers.StudentDao.findStudentById
就会找到:namespace 为 com.mybatis3.mappers.StudentDao 下面的 id = findStudentById 的 MappedStatement
MyBatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
方式一:使用标签,逐一定义列名和对象属性名之间的映射关系
<resultMap type="com.pojo.User" id="myResult">
<id property="uid" column="uid"/>
<result property="uName" column="uName"/>
</resultMap>
<select id="selectUser" resultMap="myResult">
select * from user
</select>
方式二:使用sql列的别名功能,将列别名书写为对象属性名
<select id="selectUser" resultType="com.pojo.User">
select uid AS id, uName AS name from user
</select>
resultMap
是手动提交,resultType
是自动提交。- MyBatis查询在进行select映射的时候,返回类型可以用
resultType
,也可以用resultMap
,resultType
直接表示返回类型,而resultMap
则是对外部ResultMap
的引用,但resultType
跟resultMap
不能同时存在。
MyBatis的动态sql
MyBatis动态sql可以让我们在xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
if
<if test="name!=null and name!=''">
e.emp_name = #{name, jdbcType=VARCHAR}
</if>
where
将sql放入where动态标签内,至少有一个条件符合的时候,就会插入where语句并且会将条件语句前的 and 去掉。
<where>
<if test="name!=null and name!=''">
and e.emp_name=#{name,jdbcType=VARCHAR}
</if>
<if test="dep!=null">
and e.emp_dep=#{dep.id,jdbcType=INTEGER}
</if>
</where>
set
set 可用于动态包含需要更新的列,而舍去其它的。
<update id="updateAuthorIfNecessary">update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
</set>
where id=#{id}
</update>
foreach
<select id="countByUserList" parameterType="list">
SELECT COUNT(*) FROM users WHERE user_id IN
<foreach item="userList" collection="list" separator="," open="(" close=")" index="">
#{item.userId}
</foreach>
</select>
MyBatis中一级缓存与二级缓存的区别
一级缓存是
SqlSession
级别的缓存:MyBatis对缓存提供支持,默认只开启一级缓存。
一级缓存在操作数据库时需要构造
sqlSession
对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession
之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession
中, 不同的sqlSession
中的缓存是互相不能读取的。
MyBatis的二级缓存是
mapper
级别的缓存,它可以提高对数据库查询的效率,提高应用的性能。
多个
SqlSession
去操作同一个Mapper的sql语句,多个SqlSession
可以共用二级缓存,二级缓存是跨SqlSession
的。
二级缓存开启方式:在mybatis.xml
配置文件中加入:
<span style="font-size:18px;">
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
</span>
MyBatis中的接口绑定方式
- 通过注解绑定:在接口的方法上加上
@Select
、@Update
等注解里面包含Sql语句来绑定(Sql语句比较简单的时候,推荐注解绑定) - 通过xml文件绑定:指定xml映射文件中的
namespace
为接口的全路径名(SQL语句比较复杂的时候,推荐xml绑定)
MyBatis与Hibernate的区别
- MyBatis不完全是一个ORM框架,因为MyBatis需要开发者自己编写Sql语句。
- MyBatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁。但灵活的前提是MyBatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
- Hibernate 对象/关系 映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用Hibernate开发可以节省很多代码,提高效率。