Mybatis特点
1、简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求
3、解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的ORM字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
MybatisUtils.java
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (IOException e){
e.printStackTrace();
}
}
public static SqlSession createSession(){
return sqlSessionFactory.openSession();
}
几个可以优化的地方
- 连接数据库的配置单独放在一个properties文件中
- 为实体类定义别名,简化sql映射xml文件中的引用
- 可以在src下加入log4j的配置文件,打印日志信息
动态SQL与模糊查询
<mapper namespace="com.rjxy.day03_mybatis.test6.userMapper">
<select id="getUser" parameterType="com.rjxy.day03_mybatis.test6.ConditionUser" resultType="com.rjxy.day03_mybatis.test6.User">
select * from d_user where age>=#{minAge} and age<=#{maxAge}
<if test='name!="%null%"'>and name like #{name}</if>
</select>
</mapper>
MyBatis中可用的动态SQL标签
调用存储过程
说说每行代表的含义
#创建存储过程(查询得到男性或女性的数量, 如果传入的是0就女性否则是男性)
DELIMITER $
CREATE PROCEDURE mybatis.ges_user_count(IN sex_id INT, OUT user_count INT)
BEGIN
IF sex_id=0 THEN
SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='女' INTO user_count;
ELSE
SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='男' INTO user_count;
END IF;
END
$
<mapper namespace="com.rjxy.mybatis.test7.userMapper">
<!--
查询得到男性或女性的数量, 如果传入的是0就女性否则是男性
CALL mybatis.get_user_count(1, @user_count);
-->
<select id="getCount" statementType="CALLABLE" parameterMap="getCountMap">
call mybatis.get_user_count(?,?)
</select>
<parameterMap type="java.util.Map" id="getCountMap">
<parameter property="sex_id" mode="IN" jdbcType="INTEGER"/>
<parameter property="user_count" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
</mapper>
缓存
如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用。
SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用
怎么判断某两次查询是完全相同的查询?
1、传入的statementId
2、查询时要求的结果集中的结果范围
3、这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )
4、传递给java.sql.Statement要设置的参数值
Mapper级别的缓存,拥有多个SqlSession,执行同一Mapper中的SQL语句,数据也存储在HashMap中,并且每个SqlSession中的缓存内容共享。Java类若要使用二级缓存则需要实现Serializable接口。
JDBC的执行流程有那几步。
- 加载数据库驱动
- 创建并获取数据库链接
- 创建jdbc statement对象
- 设置SQL语句
- 设置SQL语句中的参数
- 通过statement执行SQL并获取结果
- 对SQL执行结果进行解析处理
- 释放资源
简述Mybatis开发的步骤。
- 添加jar包
- 建库+表
- 添加Mybatis的配置文件conf.xml。
- 定义表所对应的实体类
- 定义操作users表的SQL映射文件userMapper.xml
- 在conf.xml文件中注册userMapper.xml文件
- 编写测试代码,执行定义的select语句
一级缓存
一级缓存是基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
SqlSession级别的缓存,缓存数据存储在HashMap中,在进行第一次查询时,首先会从数据库中查询出结果,然后将结果存在一级缓存中;当我们第二次查询时,首先会查询一级缓存,如果一级缓存没有在查询数据库。在进行CUD操作并执行了commit或关闭Sqlsession后会将缓存清空,如果二级缓存是开启的那么会将数据缓存到二级缓存中。默认一级缓存是开启的
二级缓存
二级缓存是二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache(EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点)。
Mapper级别的缓存,拥有多个SqlSession,执行同一Mapper中的SQL语句,数据也存储在HashMap中,并且每个SqlSession中的缓存内容共享。Java类若要使用二级缓存则需要实现Serializable接口。
重点说说每个标签的含义
<cache
eviction="FIFO" //回收策略为先进先出
flushInterval="60000" //自动刷新时间60s
size="512" //最多缓存512个引用对象
readOnly="true"/> //只读