、## Jdbc编程有哪些不足之处,mybatis是如何解决这些问题的?
数据库链接创建、释放频繁早晨系统资源浪费
解决,在sqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接sql语句写在带代码中不易于维护,实际应用sql变化可能很大,sql变动需要改变java代码
解决:将sql语句配置在XXXmapper.xml中与java代码分离向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要与参数一一对应
解决:mybatis自动将java对象映射至sql语句对结果集解析麻烦,sql变化导致解析变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决,mybatis将java对象映射至sql语句
mybatis的编程步骤
- 创建SqlSessionFactory
- 通过SqlSessionFactory创建SqlSession
- 通过sqlsession执行数据库操作
- 调用session.commit()提交事务
- 调用session.close()关闭会话
mybatis的交互环境
- 读取sqlMap配置文件
- 构建Statement对象集
- 创建SqlSession对象
mybatis的运行原理
- 创建SqlMapSession
- 从对象池中取出一个SessionScope对象
- 简历数据库连接
- 从对象池中取出一个RequestScope对象
- 执行SQL语句
1.映射JAVA对象参数到ParameterMap
2.映射数据库到ResultMap - 归还RequestScope
- 释放数据库连接
- 归还SessionScope
- 销毁或共享SqlMapSession
mybatis对SQL解析
情景:
acconutDao.selectAccountById(account)
加入我们执行这个查询方法,将account的Id与firstName传入,那么其映射细节是怎么样的?
- mybatis会把SqlMapConfig.xml解析成一个个Statement,其中煲剧哦ParameterMap,resultMap,以及解析后的SQL。
-传过来时候:parameterMap + 对象数据 = 提取一个参数数组,这个数组的顺序就对应与SQL中的参数的顺序 - 提交statement到数据库
- blabla看源码。。时序图不好画
数据库字段映射到Java对象
数据库执行SQL后会返回执行结果,返回的信息有两条。mybatis如何将这两条记录设置到account对象中?
ResultMap中的ResultClass创建返回对象。太复杂了。。。blabla 看源码
或者看:
使用mybatis的mapper接口调用时有哪些要求
- Mapper接口方法名和mapper.xml中定义的每个sql的id相同
- Mapper接口方法的输入参数类型与mapper.xml中定义的每个sql的parameterType的类型相同。
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
- Mapper.xml文件中的namespace即是mapper接口的类路径
SqlMapConfig.xml中配置哪些内容
顺序如下
1. properties
2. settings
3. typeAliases
4. typeHandlers
5. objectFactory
6. plugins
7. environments
8. environment
9. transactionManager
10. datasource
11. mappers
mybatis的一级缓存和二级缓存
- mapper首先去缓存中去查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis内部存储缓存使用一个HashMap,key为hashCode + sqlId + Sql语句。value为从查询出来映射的java对象
- 二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓冲可以跨SqlSession
Mapper编写有几种方式
- 接口实现类型继承SqlSessionDaoSupport
1、 在sqlMapConfig.xml中配置mapper.xml
<mappers>
<mapper resource="mapper.xml文件的地址" />
<mapper resource="mapper.xml文件的地址" />
</mappers>
2、 定义mapper接口
3、 实习类集成SqlSessionDaoSupport
4、spring配置
<bean id=" " class="mapper接口的实现">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
又见support,support通常都是一种封装与抽象
- 使用org.mybatis.spring.mapper.MapperFactoryBean
1、在SqlMapConfig.xml中配置mapper.xml的位置
如果mapper.xml和mapper接口的名称相同且在同一个目录,这里可以不用配置。
<mappers>
<mapper resource="mapper.xml文件的地址" />
<mapper resource="mapper.xml文件的地址" />
</mappers>
2、 定义mapper接口
- 使用mapper扫描器
mybatis里面的${}与#{}
源码级别分析请看:
select * from user where name = #{name};
select * from user where name = ${name};
这两句解析之后的结果都为
select * from user where name = 'zhangsan';
#{}在预处理的时候,会把参数用一个占位符?代替。这种替代发生在DBMS中。
如下:
select * from user where name = ?;
而${}只是简单的字符串替换。发生在动态解析过程中。
${}会发生sql注入的问题:
加入有这样一个sql:
select * from ${tableName} where name = #{name}
动态解析后
select * from user; delete user; -- where name = ?
–之后的语句被注释掉,而原本查询用户的语句就变成了查询所有用户信息。直接GG。
但是表名用参数传递进来的时候,只能用${}。
mybatis
Hibernate的优点是它是一个完全的ORM框架,使用Hibernate可以做到不用手写SQL,而且无须关心使用何种数据库,可移植性较好,当需要更变数据库时需要做的修改很少甚至为0。其缺点是需要根据数据库的设计在实体进行又一次的配置,且帮程序员做了太多事,如果需要进行调优的话需要对Hibernate有比较深的了解。
MyBatis的优缺点差不多和Hibernate相反,我们需要手写SQL语句和配置结果集和实体类的映射,即使是简单的单表操作也需要写SQL(可以通过拦截器来实现CommonMapper,或者可以使用生成器来生成代码),因此MyBatis要进行SQL调优也简单直接。其次是MyBatis的二级缓存功能较弱,是针对namespace的。