一共也就文章这些东西没啥了。 关键词:自己总结瞎玩🤣🤣🤣想彻底的,系统的明白看官方文档吧 1.mybatis 持久层 mapper接口映射 Mybatis核心配置 mappeer.xml pojo CRUD 2.setting mappers properties typeAliases DataSource 3.别名简化 结果映射 ResultMap 生命周期 作用域 日志 Log4j 4.注解开发 注解CRUD @param 一对多/多对一查询 association collection 5.动态SQL if 拼接 where choose set SQL片段 foreach 6.Mybatis缓存 一级缓存 二级缓存 缓存原理 7.关键点的使用
一、Mybatis使用关键点
1.Mybatis持久化理解
将程序数据在持久状态和瞬时状态间转换的机制。持久化服务的出现是由于内存本身的缺陷引起的。传统的jdbc操作 , 有很多重复代码块 .比如 : 数据取出时的封装 , 数据库的建立连接等等… , 通过框架可以减少重复代码,提高开发效率 也就是半自动化,例如医院给我们的病例单表格,我们只需要填写表格就行了,而不是给我们一张白纸,去填写。mybatis就是这样,我们往里面添加东西就行了,他自动帮我们JDBC的复杂操作。
2.Mybatis使用
maven导入依赖 配置mybatis核心配置文件 实体类编写 mybatis工具类 编写功能接口mapper(interface) 编写接口mapper相应的mapper.xml(SQL) 编写测试类
3.使用要点
1.核心配置文件(重点) 配置环境,数据源,绑定配置文件,日志, 别名, properties数据源内外分离,mapper映射绑定 2.注解开发 注解开发就代替了mapper.xml文件 ,但是仍然要进行注册 3.一对多多对一查询 按照结果嵌套处理,按照查询嵌套处理 association 关联 多对一使用 collection 集合 一对多使用 都有套路的写法 4.mybatis工具类 直接封装好,里面是获取sqlSessionFactory的获取,并可以封装一个sqlSession进行返回 5.功能接口编写 功能接口编写使用注解的话就不用写xml了但是只适用于简单的SQL 6.mapper.xml的编写(重点) (1)这里面写的都是接口要的方法功能,也就是一个功能实现所要关心的核心内容:数据的返回值,SQL语句,参数类型,参数数目,与数据库的映射对应。 (2)所以我们应该在里面写这些东西: 进行接口的映射,SQL语句的编写,参数的声明,数据库返回的结果怎么映射到我们的pojo。 (3)但是有的时候会非常烦,因为有路径名,所以还要写一些东西简化,所以就有了别名这个东西。还有可能因为查询很复杂官方文档的五表查询,所以有了association和collection帮助我们进行映射,将表关联起来,并且可以将参数完美的传递映射 7.编写测试类 编写测试类或者使用接口的时候直接根据接口所要的参数进行传递即可。 参数太多的情况下使用map集合,参数放在集合内部用的时候直接可以拿出map的key。
4.总结
以上说的都是使用过程中要注意的关键点,关键地方,也就那么几个,注册,返回结果映射,多表查询,别名,多参数使用map,接口和其他的映射,就这么多。下面要梳理的就是为了更好的使用它和要学习的知识。这些东西会很好的辅助我们去理解和使用。
二、原理和配置
1.生命周期作用域
想要承上启下,系统的了解就去看官方文档吧
- SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
- SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为 MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。
- 由于 SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。
- 因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。
- 如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭。
- 所以 SqlSession 的最佳的作用域是请求或方法作用域
2.environments
掌握的要点: 1.学会是使用配置多套运行环境 2.Mybatis默认的事务管理器JDBC,磨人的连接,有池的pooled
3.mappers元素
引入资源方式
<mappers>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
Mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
</mapper>
MyBatis 的真正强大在于它的映射语句,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 为聚焦于 SQL 而构建,以尽可能地为你减少麻烦。
4.properties优化
官方文档原话不是我说的: 这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。 数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。具体的官方文档。 我们来优化我们的配置文件 第一步 ; 在资源目录下新建一个db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456
第二步 : 将文件导入properties 配置文件 在Mybatis-config.xml文件里面写,在这里引入,进一步的内外分离了。
<configuration>
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
5.typeAliases别名
通俗解释:就是com.kuang.pojo.User这个太长了,简化一下 1.配置别名
<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>
当这样配置时,User 可以用在任何使用com.kuang.pojo.User 的地方。 2.也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
每一个在包 com.kuang.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。大写也可以,但是官方建议用小写 Java Bean别名,不用路径名了若有注解,则别名为其注解值。见下面的例子:
@Alias("user")
public class User {
...
}
去官网查看一下Mybatis默认的一些类型别名!
6.动态SQL
if元素:判断条件决定是否拼接
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog where
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
where元素:帮我们自动删除多余的and
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
set元素:帮我们自动删除,删除逗号
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id};
</update>
choose元素:类似我们的switch case ,这里的choose是只要前面的中了,后面的就不做了。
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
SQL片段:有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
注意: ①最好基于 单表来定义 sql 片段,提高片段的可重用性 ②在 sql 片段中不要包括 where
Foreach:遍历 1、编写接口
List<Blog> queryBlogForeach(Map map);
2、编写SQL语句
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
7.日志
1.学会看日志 2.学会日志的相关配置 3.但是基本上相关的配置我们都不自己写,都是看网上大神设计好的🤣🤣 4.学会log4j
8.缓存
1.一级缓存 本地缓存基于会话session,无法关闭,close后失效 2.二级缓存 全局缓存基于namescapeye也就是基于mapper,默认开启。但是我们要显示的把他开启。以免别人看不懂。 3.二级缓存的使用 开启全局缓存 【mybatis-config.xml】
<setting name="cacheEnabled" value="true"/>
去每个mapper.xml中配置使用二级缓存,这个配置非常简单;【xxxMapper.xml】
<cache/>
官方示例=====>查看官方文档
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
代码测试
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
session.close();
User user2 = mapper2.queryUserById(1);
System.out.println(user2);
System.out.println(user==user2);
session2.close();
}
结论
- 只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据
- 查出的数据都会被默认先放在一级缓存中
- 只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中
4.一级缓存失效的四种情况 一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;
一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求!
①sqlSession不同
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
User user2 = mapper2.queryUserById(1);
System.out.println(user2);
System.out.println(user==user2);
session.close();
session2.close();
}
观察结果:发现发送了两条SQL语句!
结论:每个sqlSession中的缓存相互独立
②sqlSession相同,查询条件不同
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
UserMapper mapper2 = session.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
User user2 = mapper2.queryUserById(2);
System.out.println(user2);
System.out.println(user==user2);
session.close();
}
观察结果:发现发送了两条SQL语句!很正常的理解
结论:当前缓存中,不存在这个数据
③sqlSession相同,两次查询之间执行了增删改操作!
增加方法
int updateUser(Map map);
编写SQL
<update id="updateUser" parameterType="map">
update user set name = #{name} where id = #{id}
</update>
测试
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
HashMap map = new HashMap();
map.put("name","kuangshen");
map.put("id",4);
mapper.updateUser(map);
User user2 = mapper.queryUserById(1);
System.out.println(user2);
System.out.println(user==user2);
session.close();
}
观察结果:查询在中间执行了增删改操作后,重新执行了
结论:因为增删改操作可能会对当前数据产生影响
④sqlSession相同,手动清除一级缓存
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
session.clearCache();
User user2 = mapper.queryUserById(1);
System.out.println(user2);
System.out.println(user==user2);
session.close();
}
解释:感觉一级缓存就是一个map
三、其他
1.其他配置
看官网吧,他更np
2.涉及到的实际模式
工厂模式,代理模式,建造者模式
3.limit分页
4.注解开发
5.一对多,多对一
mybatis也就这点东西了,没啥了,,没写到没理解的,多看官方文档吧。 Mybatis结束
|