Mybatis下.md

本文详细介绍了Mybatis的一级缓存、二级缓存的使用及例外情况,以及高级结果映射中的嵌套查询,包括一对一、一对多的映射实现。此外,还探讨了延迟加载的概念及其在不同场景下的表现。

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);

    }

开启二级缓存

  1. 在mapper 文件中设置 <cache/>
  2. 在实体类中实现序列化接口

命中:

@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 高级结果映射-嵌套查询

执行流程

  1. 先执行一次单表查询
  2. 再利用单表查询的结果继续执行其他单表查询
  3. 最后组装结果映射

一对一

  1. 修改pojo 文件,在blog中添加author对象
    private Author author; // 一个blog 对应一个 author

  1. 修改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>
  1. 接口
  2. 测试

返回所有blog

    <select id="selectBlogList" resultMap="blogResultMap">
        select * from blog
    </select>

查询blog列表时,执行的sql 语句是 1 + n, 但是如果blog 关联的author 有重复的数据,那么会从一级缓存中查询。结果有6条blog, 但是只查询了3此author, 因为走了1级缓存。

如果开启了二级缓存,那么还有更加节约资源,所以如果有的东西实时性更新不频繁,那么可以开启二级缓存

一对多

一个post 有多个comment, 首先设置

  1. pojo private List<Comment> commentList;
  2. 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 是实体类或者实体类的集合就不能随便写

  1. 接口

Post selectPostId(Integer postId); List<Comment> selectCommentByPostId(Integer pid);

  1. 测试
    @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 高级结果映射- 嵌套结果

  1. 先执行关联查询, 一次性将所有数据都查询出来
  2. 再将所有查询出来的列组织成嵌套的结果对象 (效率高,开发麻烦)

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 构造方法调用

  1. Blog 实体类的构造方法
public Blog(Integer id, String title){
        super();
        this.id = id;
        this.title = title;
        System.out.println("构造方法+++");

    }
  1. 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 对象

  1. 打开jdbc 连接
  2. 创建一个connection
  3. 开启事务
  4. 执行查询Blog
  5. 又执行查询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() 后,也会自动查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值