文章目录
15 Mybatis generator
https://blog.youkuaiyun.com/hua_faded/article/details/78900780
16 性能-一級緩存
一级缓存,默认存在,
@Test
public void testSelectBlogCacheLevelOne() {
SqlSession session = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1);
System.out.println("结果已经查询");
Blog blog1 = blogMapper.selectBlog(1);
System.out.println("结果已经查询,从缓存中获取数据");
session.close();
System.out.println(blog);
}
当在同一个session范围内执行查询的时候,如果执行相同的查询,那么第二次查询会从缓存种获取数据
例外
如果两次查询之间有增删改操作, sql session 缓存区会被自动清空,说明下一次查询会重新执行sql语句
@Test
public void testSelectBlogCacheLevelOne() {
SqlSession session = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1);
System.out.println("结果已经查询");
blog.setFeatured(true);
blogMapper.updateBlog(blog);
System.out.println("刷新缓存");
Blog blog1 = blogMapper.selectBlog(1);
System.out.println("重新执行查询");
session.commit();
session.close();
System.out.println(blog);
}
17 二级缓存
默认不开启,如果在不同的session范围内,执行相同的数据查询,那么每次查询会执行独立的数据库检索过程
@Test
public void testSelectBlogCacheLevelOne() {
SqlSession session1 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session1.getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1);
session1.close();
System.out.println("session1 关闭");
System.out.println(blog);
SqlSession session2 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
blog = blogMapper2.selectBlog(1);
session2.close();
System.out.println("session2 关闭");
System.out.println(blog);
}
开启二级缓存
- 在mapper 文件中设置
<cache/> - 在实体类中实现序列化接口
命中:
@Test
public void testSelectBlogCacheLevelOne() {
SqlSession session1 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session1.getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1);
session1.close();
System.out.println("session1 关闭");
System.out.println(blog);
SqlSession session2 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
blog = blogMapper2.selectBlog(1);
session2.close();
System.out.println("session2 关闭");
System.out.println(blog);
}
缓存被刷新
@Test
public void testSelectBlogCacheLevelOne() {
SqlSession session1 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session1.getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1);
blog.setFeatured(true);
blogMapper.updateBlog(blog);
System.out.println("刷新缓存");
session1.close();
System.out.println("session1 关闭");
System.out.println(blog);
SqlSession session2 = MyBatisUtil.getSqlSession();
BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
blog = blogMapper2.selectBlog(1);
session2.close();
System.out.println("session2 关闭");
System.out.println(blog);
}
18 高级结果映射-嵌套查询
执行流程
- 先执行一次单表查询
- 再利用单表查询的结果继续执行其他单表查询
- 最后组装结果映射
一对一
- 修改pojo 文件,在blog中添加author对象
private Author author; // 一个blog 对应一个 author
- 修改mapper.xml
blog:
<mapper namespace="com.leiqingqi.mybatis.mapper.BlogMapper">
<resultMap id="blogResultMap" type="Blog">
<id column="id" property="id" jdbcType="INTEGER"/> <!--这一行可以去掉-->
<association property="author" column="author_id"
select="com.leiqingqi.mybatis.mapper.AuthorMapper.selectAuthorById"
/> <!--!!!!!!!!!!!!!!, 用author 的id 查author-->
</resultMap>
<select id="selectBlogById" parameterType="int" resultMap="blogResultMap">
select * from blog where id = #{id}
</select>
</mapper>
Author:
<mapper namespace="com.leiqingqi.mybatis.mapper.AuthorMapper">
<resultMap id="authorResultMap" type="Author">
<id column="id" property="id" jdbcType="INTEGER"/>
<id column="favourite_section" property="favouriteSection" jdbcType="VARCHAR"/>
</resultMap>
<select id="selectAuthorById" parameterType="int" resultMap="authorResultMap">
select * from author where id = #{id}
</select>
</mapper>
- 接口
- 测试
返回所有blog
<select id="selectBlogList" resultMap="blogResultMap">
select * from blog
</select>
查询blog列表时,执行的sql 语句是 1 + n, 但是如果blog 关联的author 有重复的数据,那么会从一级缓存中查询。结果有6条blog, 但是只查询了3此author, 因为走了1级缓存。
如果开启了二级缓存,那么还有更加节约资源,所以如果有的东西实时性更新不频繁,那么可以开启二级缓存
一对多
一个post 有多个comment, 首先设置
- pojo
private List<Comment> commentList; - mapper.xml
PostMapper.xml
<resultMap id="postResultMap" type="Post">
<id column="id" property="id" jdbcType="INTEGER"/>
<!-- column 的id 是post 的id, 通过postid 在comment 中匹配-->
<collection property="commentList" column="id" javaType="ArrayList" ofType="Comment"
select="com.leiqingqi.mybatis.mapper.CommentMapper.selectCommentByPostId"/>
</resultMap>
<select id="selectPostId" parameterType="int" resultMap="postResultMap">
select * from post where id = #{id}
</select>
CommentMapper.xml
通过post_id 来给comment 分类
<select id="selectCommentByPostId" parameterType="int" resultMap="commentResultMap">
select * from comment where post_id = #{postId}
</select>
关于mapper.xml 中的SQL #{} 中该怎么写, parameterType 是单值随便写, parameterType 是实体类或者实体类的集合就不能随便写
- 接口
Post selectPostId(Integer postId); List<Comment> selectCommentByPostId(Integer pid);
- 测试
@Test
public void testSelectPostId(){
SqlSession session = MybatisUtil.getSqlSession();
PostMapper postMapper = session.getMapper(PostMapper.class);
Post post = postMapper.selectPostId(1);
session.close();
System.out.println(post);
}
19 高级结果映射- 嵌套结果
- 先执行关联查询, 一次性将所有数据都查询出来
- 再将所有查询出来的列组织成嵌套的结果对象 (效率高,开发麻烦)
SELECT * FROM blog b left join author a on b.author_id = a.id;
20 扩展结果
很多时候并不需要嵌套查询,查询博客不需要查询作者的所有信息,只需知道作者名字就行了,作者的详细信息可以当用户点击后显示,我们使用逆向工程生成代码后,不能修改实体类,因为再mapper.xml 文件很难修改。
BlogCustom 类 extends Blog
public class BlogCustom extends Blog {
private String authorUsername;
public String getAuthorUsername() {
return authorUsername;
}
public void setAuthorUsername(String authorUsername) {
this.authorUsername = authorUsername;
}
@Override
public String toString() {
return "BlogCustom{" +
"authorUsername='" + authorUsername + '\'' +
'}'+super.toString();
}
}
xml: left join:
<mapper namespace="com.leiqingqi.mybatis.mapper.BlogMapperCustom">
<sql id = "columnBase">
b.id, b.title, b.author_id as authorId, b.state, b.featured, b.style,
a.username as authorUsername
</sql>
<select id="selectBlogById" parameterType="int" resultType="BlogCustom">
select
<include refid="columnBase"/>
from blog b left join author a on b.author_id = a.id where b.id = #{id}
</select>
</mapper>
接口
public interface BlogMapperCustom {
BlogCustom selectBlogById(Integer id);
}
测试:
@Test
public void testSelectBlogCustom(){
SqlSession session = MybatisUtil.getSqlSession();
BlogMapperCustom blogMapper = session.getMapper(BlogMapperCustom.class);
Blog blog = blogMapper.selectBlogById(1);
System.out.println(blog);
session.close();
}
21 构造方法调用
- Blog 实体类的构造方法
public Blog(Integer id, String title){
super();
this.id = id;
this.title = title;
System.out.println("构造方法+++");
}
- BlogMapper.xml 文件
<resultMap id="blogResultMapConstructor" type="Blog">
<constructor>
<idArg column="id" javaType="int"/>
<arg column="title" javaType="string"/>
</constructor>
</resultMap>
<select id="selectBlogByIdContructor" parameterType="int" resultMap="blogResultMapConstructor">
select * from blog where id = #{id}
</select>
21 鉴别器
有的时候比如说把车分类,有时候不想弄两张表,外键约束,只在一张表上表明车的类别,比如1代表轿车
2代表 SUV
<resultMap type="Vehicle" id="vehicleResultMap">
<id column="id" property="id" jdbcType="INTEGER"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultType="Car">
<result column="door_count" property="doorCount"/>
</case>
<case value="2" resultType="Suv">
<result column="all_wheel_drive" property="allWheelDrive"/>
</case>
</discriminator>
</resultMap>
<select id="selectVehicleById" parameterType="int" resultMap="vehicleResultMap">
select * from vehicle where id=#{id}
</select>
22 延迟加载
查询Blog
测试一:积极加载
没有配置任何选项,无论是否查询blog的任意属性,都会执行author数据的查询,因为blog中有一个author对象,我们写了sql 语句来查询author 来定义blog 中的author 对象
- 打开jdbc 连接
- 创建一个connection
- 开启事务
- 执行查询Blog
- 又执行查询Author
只要查询Blog 就查询Author
==> Preparing: select * from blog where id = ?
==> Parameters: 1(Integer)
<== Total: 1
==> Preparing: select * from author where id = ?
==> Parameters: 1(Integer)
<== Total: 1
测试二: 延迟加载
配置了全局属性
<setting name="lazyLoadingEnabled" value="true"/>
如: 再mybatis-config.xml 中
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="useGeneratedKeys" value="true"/> <!--在自增主键表中使用这个获得自增id-->
<setting name="lazyLoadingEnabled" value="true"/> <!--延迟加载-->
</settings>
如果没有使用author, 则不会查询author
懒惰延迟加载
还要配置
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
但是如果用到author 还是会查询,即使是在session.close() 后,也会自动查询。
本文详细介绍了Mybatis的一级缓存、二级缓存的使用及例外情况,以及高级结果映射中的嵌套查询,包括一对一、一对多的映射实现。此外,还探讨了延迟加载的概念及其在不同场景下的表现。
803

被折叠的 条评论
为什么被折叠?



