mybatis_du笔记详细版3(高级映射,缓存,分页,注解)

1.高级映射

多对一

数据库上来讲,比如多个学生对应一个班级

所以在pojo类中这样设计:将班级放到pojo类里面。但是是两张表的数据

public class Student { // Student是多的一方
    private Integer sid;
    private String sname;
    private Clazz clazz; // Clazz是一的一方。
public class Clazz {
    private Integer cid;
    private String cname;

    private List<Student> stus;

查询某个学生和他的班级信息:

方法一:使用一条sql语句,resultmap使用级联属性映射,写的少

 <!--多对一映射的第一种方式:一条SQL语句,级联属性映射。-->
    <resultMap id="studentResultMap" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <result property="clazz.cid" column="cid"/>
        <result property="clazz.cname" column="cname"/>
    </resultMap>

    <select id="selectById" resultMap="studentResultMap">
        select
            s.sid,s.sname,c.cid,c.cname
        from
            t_stu s left join t_clazz c on s.cid = c.cid
        where
            s.sid = #{sid}
    </select>

方法二:较为规范结构清晰,使用association

<!--一条SQL语句,association。-->
    <resultMap id="studentResultMapAssociation" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <!--
            association:翻译为关联。一个Student对象关联一个Clazz对象
                property:提供要映射的POJO类的属性名。
                javaType:用来指定要映射的java类型。
        -->
        <association property="clazz" javaType="Clazz">
            <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>

    <select id="selectByIdAssociation" resultMap="studentResultMapAssociation">
        select
            s.sid,s.sname,c.cid,c.cname
        from
            t_stu s left join t_clazz c on s.cid = c.cid
        where
            s.sid = #{sid}
    </select>

 方法三:使用分部查询:这种查询方式是将需要的查询分成两个步骤,写在两个不同的文件里面

只需要在resultmap中调用另一个查询的全路径,然后传递参数。

<!--
        分步查询的优点:
            第一:复用性增强。可以重复利用。(大步拆成N多个小碎步。每一个小碎步更加可以重复利用。)
            第二:采用这种分步查询,可以充分利用他们的延迟加载/懒加载机制。
        什么是延迟加载(懒加载),有什么用?
            延迟加载的核心原理是:用的时候再执行查询语句。不用的时候不查询。
            作用:提高性能。尽可能的不查,或者说尽可能的少查。来提高效率。
        在mybatis当中怎么开启延迟加载呢?
            association标签中添加fetchType="lazy"
            注意:默认情况下是没有开启延迟加载的。需要设置:fetchType="lazy"
            这种在association标签中配置fetchType="lazy",是局部的设置,只对当前的association关联的sql语句起作用。

        在实际的开发中,大部分都是需要使用延迟加载的,所以建议开启全部的延迟加载机制:
            在mybatis核心配置文件中添加全局配置:lazyLoadingEnabled=true

        实际开发中的模式:
            把全局的延迟加载打开。
            如果某一步不需要使用延迟加载,请设置:fetchType="eager"
    -->
    <!--两条SQL语句,完成多对一的分步查询。-->
    <!--这里是第一步:根据学生的id查询学生的所有信息。这些信息当中含有班级id(cid)-->
    <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <association property="clazz"
                     select="com.powernode.mybatis.mapper.ClazzMapper.selectByIdStep2"
                     column="cid"
                     fetchType="eager"/>
    </resultMap>

    <select id="selectByIdStep1" resultMap="studentResultMapByStep">
        select sid,sname,cid from t_stu where sid = #{sid}
    </select>

<!--分步查询第二步:根据cid获取班级信息。-->这个是另一个mapper文件中内容

    <select id="selectByIdStep2" resultType="Clazz">
        select cid,cname from t_clazz where cid = #{cid}
    </select>

一对多的映射关系

 方法一:使用的标签是集合标签collection

<resultMap id="clazzResultMap" type="Clazz">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <!--一对多,这里是collection。collection是集合的意思。-->
        <!--ofType 属性用来指定集合当中的元素类型。-->
        <collection property="stus" ofType="Student">
            <id property="sid" column="sid"/>
            <result property="sname" column="sname"/>
        </collection>
    </resultMap>

    <select id="selectByCollection" resultMap="clazzResultMap">
        select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid = s.cid where c.cid = #{cid}
    </select>

方法二:分部查询

<!--分步查询第一步:根据班级的cid获取班级信息。-->
    <resultMap id="clazzResultMapStep" type="Clazz">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <collection property="stus"
                    select="com.powernode.mybatis.mapper.StudentMapper.selectByCidStep2"
                    column="cid" fetchType="eager" />
    </resultMap>

    <select id="selectByStep1" resultMap="clazzResultMapStep">
        select cid,cname from t_clazz where cid = #{cid}
    </select>
<select id="selectByCidStep2" resultType="Student">
        select * from t_stu where cid = #{cid}
    </select>

2.mybaits的缓存技术

缓存:提前把数据方法缓存中(内存中),下次用的时候直接用缓存中提取,效率高

mybatis执行查询语句的时候会将查询结果放到缓存中,如果下一次还是执行完全相同的sql,那么会直接从缓存中取数据,不再查询数据库

缓存机制:通过减少io的方式提高效率

一般的缓存机制有:字符串常量池,整数常量池,线程池,连接池等

 mybatis缓存包括:

一级缓存:将查询到的数据存放到sqlsession中

二级缓存:将查询到的数据存放到SqlSessionFactory(整个数据库就一个)

一级缓存 

默认是直接开启的,在同一个SqlSession会话中存在缓存

在查询条件一致和SqlSession对象是同一个的情况下会执行缓存

如果在第一次DQL(查询)和第二次DQL之间:

执行了sqlsession的clearcache方法

执行了增删改方法,这里要注意不管你操作的这张表是不是你缓存中的数据,都会清空。

都会清空一级缓存

二级缓存

默认是开启的,在同一个SqlSessionFactory中

需要在对应的mapper文件中添加<cache/>标签 

使用二级缓存的实体类必须序列化

必须在sqlsession对象提交或者关闭之后才会写入二级缓存

查询的时候首先会查询一级缓存,然后查询二级缓存,然后数据库。

出现增删改的时候二级缓存也会直接失效

eviction:指定从缓存中移除某个对象的淘汰算法。默认采用LRU策略。

  • LRU:Least Recently Used。最近最少使用。优先淘汰在间隔时间内使用频率最低的对象。(其实还有一种淘汰算法LFU,最不常用。)
  • FIFO:First In First Out。一种先进先出的数据缓存器。先进入二级缓存的对象最先被淘汰。
  •  SOFT:软引用。淘汰软引用指向的对象。具体算法和JVM的垃圾回收算法有关。
  • WEAK:弱引用。淘汰弱引用指向的对象。具体算法和JVM的垃圾回收算法有关

2. flushlnterval:
a. 二级缓存的刷新时间间隔。单位毫秒。如果没有设置。就代表不刷新缓存,只要内存足够大,一直会向二级缓存中缓存数据。除非执行了增删改。
3. readOnly:
a. true:多条相同的sql语句执行之后返回的对象是共享的同一个。性能好。但是多线程并发可能会存在安全问题。
b. false:多条相同的sql语句执行之后返回的对象是副本,调用了clone方法。性能一般。但安全。
size:
a.设置二级缓存中最多可存储的java对象数量。默认值1024。

集成Ehcache缓存

就是第三方的缓存机制,是用来替代二级缓存的无法替代一级缓存 

3.mybatis的分页 

第一步:引入依赖

<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.1</version>
        </dependency>

第二部:在核心配置文件中配置

  <!--mybatis分页的拦截器-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

第三步:使用

在执行正常的查询之前必须要先开启分页功能,然后mybatis才会根据这个再拦截一部分信息

然后可以根据我们现在分页的信息封装到一个pageInfo类中,这个类中存放了分页的详细信息

  @Test
    public void testSelectAll(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);

        // 一定一定一定要注意:在执行DQL语句之前。开启分页功能。
        int pageNum = 2;
        int pageSize = 3;
        PageHelper.startPage(pageNum, pageSize);

        List<Car> cars = mapper.selectAll();
        //cars.forEach(car -> System.out.println(car));

        // 封装分页信息对象new PageInfo()
        // PageInfo对象是PageHelper插件提供的,用来封装分页相关的信息的对象。
        PageInfo<Car> carPageInfo = new PageInfo<>(cars, 3);

        System.out.println(carPageInfo);

        sqlSession.close();

        /*
        PageInfo{pageNum=2, pageSize=3, size=3, startRow=4, endRow=6, total=7, pages=3,
        list=Page{count=true, pageNum=2, pageSize=3, startRow=3, endRow=6, total=7, pages=3, reasonable=false, pageSizeZero=false}
        [Car{id=168, carNum='1204', brand='奥迪Q7', guidePrice=3.0, produceTime='2009-10-11', carType='燃油车'},
        Car{id=169, carNum='1205', brand='朗逸', guidePrice=4.0, produceTime='2001-10-11', carType='新能源'},
        Car{id=170, carNum='1206', brand='奔驰E300L', guidePrice=50.0, produceTime='2003-02-03', carType='新能源'}],
        prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true,
        navigatePages=3, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}
         */
    }

基于主机的crud

就是直接使用@insert @update这种注解直接写在接口方法上,然后直接编写sql语句。对于简单的sql语句来说更加方便,但是对于复杂的没有写xml映射文件好用。也不重要。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值