MyBatis的缓存、逆向工程、使用PageHelper、使用PageHelper

一、MyBatis的缓存

缓存:cache

缓存的作用:通过减少IO的方式,来提高程序的执行效率。

mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下一次还是这条select语句的话,直接从缓存中取,不再查数据库。一方面是减少了IO。另一方面不再执行繁琐的查找算法。效率大大提升。

mybatis缓存包括:

  • 一级缓存:将查询到的数据存储到SqlSession中。

  • 二级缓存:将查询到的数据存储到SqlSessionFactory中。

  • 或者集成其它第三方的缓存:比如EhCache【Java语言开发的】、Memcache【C语言开发的】等。

缓存只针对于DQL语句,也就是说缓存机制只对应select语句。

1.一级缓存

一级缓存默认是开启的。不需要做任何配置。

原理:只要使用同一个SqlSession对象执行同一条SQL语句,就会走缓存。

模块名:mybatis-010-cache

复制代码
public interface CarMapper {

    /**
     * 根据id获取Car信息。
     * @param id
     * @return
     */
    Car selectById(Long id);
}

<?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="org.example1.mapper.CarMapper">


    <select id="selectById" resultType="Car">
        select * from t_car where id = #{id}
    </select>
    
</mapper>

Test

复制代码
    @Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();

        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
        Car car1 = mapper1.selectById(33L);
        System.out.println(car1);


        CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
        Car car2 = mapper2.selectById(33L);
        System.out.println(car2);

        sqlSession.commit();
        sqlSession.close();
    }

什么情况下不走缓存?

  • 第一种:不同的SqlSession对象。

  • 第二种:查询条件变化了。

    复制代码
      @Test
      public void testSelectById() throws Exception{
          // 如果要获取不同的SqlSession对象,不能使用以下代码。
          //SqlSession sqlSession = SqlSessionUtil.openSession();
    
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
          SqlSession sqlSession1 = sqlSessionFactory.openSession();
          SqlSession sqlSession2 = sqlSessionFactory.openSession();
    
          CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
          Car car1 = mapper1.selectById(33L);
          System.out.println(car1);
    
          CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
          Car car2 = mapper2.selectById(33L);
          System.out.println(car2);
    
          sqlSession1.close();
          sqlSession2.close();
      }

一级缓存失效情况包括两种:

  • 第一种:第一次查询和第二次查询之间,手动清空了一级缓存。

    sqlSession.clearCache();

  • 第二种:第一次查询和第二次查询之间,执行了增删改操作。【这个增删改和哪张表没有关系,只要有insert delete update操作,一级缓存就失效。】

    复制代码
      @Test
      public void testSelectById(){
          SqlSession sqlSession = SqlSessionUtil.openSession();
    
          CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
          Car car1 = mapper1.selectById(33L);
          System.out.println(car1);
    
          // 手动清空一级缓存
         sqlSession.clearCache();
    
    
          CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
          Car car2 = mapper2.selectById(33L);
          System.out.println(car2);
    
          sqlSession.commit();
          sqlSession.close();
      }

CarMapper接口:写的是在t_clazz表里插入数据

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;

public interface CarMapper {

  

    /**
     * 保存班级信息
     * @param cid
     * @param cname
     * @return
     */
    int insertClazz(@Param("cid") Integer cid, @Param("cname") String cname);



}

 <insert id="insertClazz">
        insert into t_clazz values(#{cid},#{cname})
    </insert>

test

复制代码
    @Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();

        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
        Car car1 = mapper1.selectById(33L);
        System.out.println(car1);


        // 在这里执行了INSERT DELETE UPDATE中的任意一个语句。并且和表没有关系。
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        mapper.insertClazz(2000, "高三三班");

        CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
        Car car2 = mapper2.selectById(33L);
        System.out.println(car2);

        sqlSession.commit();
        sqlSession.close();
    }

2.二级缓存

二级缓存的范围是SqlSessionFactory。 使用二级缓存需要具备以下几个条件:

  1. <setting name="cacheEnabled" value="true"> 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认就是true,无需设置。

  2. 在需要使用二级缓存的SqlMapper.xml文件中添加配置:<cache />

  3. 使用二级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接口

  4. SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中。此时二级缓存才可用。

测试二级缓存:

复制代码
<cache/>

public class Car implements Serializable {
//......
}

    @Test
    public void testSelectById2() throws Exception{
        // 这里只有一个SqlSessionFactory对象。二级缓存对应的就是SqlSessionFactory。
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);

        // 这行代码执行结束之后,实际上数据是缓存到一级缓存当中了。(sqlSession1是一级缓存。)
        Car car1 = mapper1.selectById2(33L);
        System.out.println(car1);

        // 如果这里不关闭SqlSession1对象的话,二级缓存中还是没有数据的。

 
        // 这行代码执行结束之后,实际上数据会缓存到一级缓存当中。(sqlSession2是一级缓存。)
        Car car2 = mapper2.selectById2(33L);
        System.out.println(car2);

        // 程序执行到这里的时候,会将sqlSession1这个一级缓存中的数据写入到二级缓存当中。
       sqlSession1.close();
        // 程序执行到这里的时候,会将sqlSession2这个一级缓存中的数据写入到二级缓存当中。
        sqlSession2.close();
    }

把sqlSession1的一级缓存中的数据会放到二级缓存当中

复制代码
    @Test
    public void testSelectById2() throws Exception{
        // 这里只有一个SqlSessionFactory对象。二级缓存对应的就是SqlSessionFactory。
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);

        // 这行代码执行结束之后,实际上数据是缓存到一级缓存当中了。(sqlSession1是一级缓存。)
        Car car1 = mapper1.selectById2(33L);
        System.out.println(car1);

        // 如果这里不关闭SqlSession1对象的话,二级缓存中还是没有数据的。

        // 如果执行了这行代码,sqlSession1的一级缓存中的数据会放到二级缓存当中。
        sqlSession1.close();

        // 这行代码执行结束之后,实际上数据会缓存到一级缓存当中。(sqlSession2是一级缓存。)
        Car car2 = mapper2.selectById2(33L);
        System.out.println(car2);

        // 程序执行到这里的时候,会将sqlSession1这个一级缓存中的数据写入到二级缓存当中。
        //sqlSession1.close();
        // 程序执行到这里的时候,会将sqlSession2这个一级缓存中的数据写入到二级缓存当中。
        sqlSession2.close();
    }

二级缓存的失效:只要两次查询之间出现了增删改操作。二级缓存就会失效。【一级缓存也会失效】

二级缓存的相关配置:

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

    1. LRU:Least Recently Used。最近最少使用。优先淘汰在间隔时间内使用频率最低的对象。(其实还有一种淘汰算法LFU,最不常用。)

    2. FIFO:First In First Out。一种先进先出的数据缓存器。先进入二级缓存的对象最先被淘汰。

    3. SOFT:软引用。淘汰软引用指向的对象。具体算法和JVM的垃圾回收算法有关。

    4. WEAK:弱引用。淘汰弱引用指向的对象。具体算法和JVM的垃圾回收算法有关。

  2. flushInterval:

    1. 二级缓存的刷新时间间隔。单位毫秒。如果没有设置。就代表不刷新缓存,只要内存足够大,一直会向二级缓存中缓存数据。除非执行了增删改。
  3. readOnly:

    1. true:多条相同的sql语句执行之后返回的对象是共享的同一个。性能好。但是多线程并发可能会存在安全问题。

    2. false:多条相同的sql语句执行之后返回的对象是副本,调用了clone方法。性能一般。但安全。

  4. size:

    1. 设置二级缓存中最多可存储的java对象数量。默认值1024。

3.MyBatis集成EhCache

集成EhCache是为了代替mybatis自带的二级缓存。一级缓存是无法替代的。

mybatis对外提供了接口,也可以集成第三方的缓存组件。比如EhCache、Memcache等。都可以。

EhCache是Java写的。Memcache是C语言写的。所以mybatis集成EhCache较为常见,按照以下步骤操作,就可以完成集成:

第一步:引入mybatis整合ehcache的依赖。

复制代码
<!--mybatis集成ehcache的组件-->
<dependency>
  <groupId>org.mybatis.caches</groupId>
  <artifactId>mybatis-ehcache</artifactId>
  <version>1.2.2</version>
</dependency>

第二步:在类的根路径下新建echcache.xml文件,并提供以下配置信息。

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存-->
    <diskStore path="e:/ehcache"/>
  
    <!--defaultCache:默认的管理策略-->
    <!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断-->
    <!--maxElementsInMemory:在内存中缓存的element的最大数目-->
    <!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上-->
    <!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false-->
    <!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问-->
    <!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问-->
    <!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->
    <!--FIFO:first in first out (先进先出)-->
    <!--LFU:Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存-->
    <!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>

</ehcache>

第三步:修改SqlMapper.xml文件中的<cache/>标签,添加type属性。

复制代码
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

    @Test
    public void testSelectById2() throws Exception{
        // 这里只有一个SqlSessionFactory对象。二级缓存对应的就是SqlSessionFactory。
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);

        // 这行代码执行结束之后,实际上数据是缓存到一级缓存当中了。(sqlSession1是一级缓存。)
        Car car1 = mapper1.selectById2(33L);
        System.out.println(car1);

        // 如果这里不关闭SqlSession1对象的话,二级缓存中还是没有数据的。

        // 如果执行了这行代码,sqlSession1的一级缓存中的数据会放到二级缓存当中。
        sqlSession1.close();

        // 这行代码执行结束之后,实际上数据会缓存到一级缓存当中。(sqlSession2是一级缓存。)
        Car car2 = mapper2.selectById2(33L);
        System.out.println(car2);

        // 程序执行到这里的时候,会将sqlSession1这个一级缓存中的数据写入到二级缓存当中。
        //sqlSession1.close();
        // 程序执行到这里的时候,会将sqlSession2这个一级缓存中的数据写入到二级缓存当中。
        sqlSession2.close();
    }

二、MyBatis的逆向工程

所谓的逆向工程是:根据数据库表逆向生成Java的pojo类,SqlMapper.xml文件,以及Mapper接口类等。

要完成这个工作,需要借助别人写好的逆向工程插件。

思考:使用这个插件的话,需要给这个插件配置哪些信息?

  • pojo类名、包名以及生成位置。

  • SqlMapper.xml文件名以及生成位置。

  • Mapper接口名以及生成位置。

  • 连接数据库的信息。

  • 指定哪些表参与逆向工程。

  • ......

1.逆向工程配置与生成

第一步:基础环境准备

新建模块:mybatis-011-generator 打包方式:jar

第二步:在pom中添加逆向工程插件

复制代码
<!--定制构建过程-->
<build>
  <!--可配置多个插件-->
  <plugins>
    <!--其中的一个插件:mybatis逆向工程插件-->
    <plugin>
      <!--插件的GAV坐标-->
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-maven-plugin</artifactId>
      <version>1.4.1</version>
      <!--允许覆盖-->
      <configuration>
        <overwrite>true</overwrite>
      </configuration>
      <!--插件的依赖-->
      <dependencies>
        <!--mysql驱动依赖-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.30</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

第三步:配置generatorConfig.xml

该文件名必须叫做:generatorConfig.xml 该文件必须放在类的根路径下。

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--
        targetRuntime有两个值:
            MyBatis3Simple:生成的是基础版,只有基本的增删改查。
            MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3Simple">
        <!--防止生成重复代码-->
        <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>

        <commentGenerator>
            <!--是否去掉生成日期-->
            <property name="suppressDate" value="true"/>
            <!--是否去除注释-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--连接数据库信息-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/jdbc"
                        userId="root"
                        password="abc123">
        </jdbcConnection>

        <!-- 生成pojo包名和位置 -->
        <javaModelGenerator targetPackage="org.example1.pojo" targetProject="src/main/java">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
            <!--是否去除字段名的前后空白-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- 生成SQL映射文件的包名和位置 -->
        <sqlMapGenerator targetPackage="org.example1.mapper" targetProject="src/main/resources">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- 生成Mapper接口的包名和位置 -->
        <javaClientGenerator
                type="xmlMapper"
                targetPackage="org.example1.mapper"
                targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!-- 表名和对应的实体类名-->
        <table tableName="t_car" domainObjectName="Car"/>

    </context>
</generatorConfiguration>

第四步:运行插件

2.测试逆向工程生成的是否好用

第一步:环境准备

  • 依赖:mybatis依赖、mysql驱动依赖、junit依赖、logback依赖

  • jdbc.properties

  • mybatis-config.xml

  • logback.xml

第二步:编写测试程序

复制代码
    @Test
    public void testSelectAll(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAll();
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

    @Test
    public void testDeleteByPrimaryKey(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int count = mapper.deleteByPrimaryKey(33L);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }
复制代码
    // CarExample类负责封装查询条件的。
    @Test
    public void testSelect(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        // 执行查询
        // 1. 查询一个
        Car car = mapper.selectByPrimaryKey(32L);
        System.out.println(car);
        // 2. 查询所有(selectByExample,根据条件查询,如果条件是null表示没有条件。)
        List<Car> cars = mapper.selectByExample(null);
        cars.forEach(car1 -> System.out.println(car1));
        System.out.println("=========================================");
        // 3. 按照条件进行查询
        // QBC 风格:Query By Criteria 一种查询方式,比较面向对象,看不到sql语句。
        // 封装条件,通过CarExample对象来封装查询条件
        //把where后面的条件封装起来
        CarExample carExample = new CarExample();
        // 调用carExample.createCriteria()方法来创建查询条件
        carExample.createCriteria()
                   .andBrandLike("帕萨特")
                   .andGuidePriceGreaterThan(new BigDecimal(20.0));
        // 添加or
        carExample.or().andCarTypeEqualTo("燃油车");
        // 执行查询
        List<Car> cars2 = mapper.selectByExample(carExample);
        cars2.forEach(car2 -> System.out.println(car2));

        sqlSession.close();

    }

三、MyBatis使用PageHelper

1.limit分页

mysql的limit后面两个数字:

  • 第一个数字:startIndex(起始下标。下标从0开始。)

  • 第二个数字:pageSize(每页显示的记录条数)

假设已知页码pageNum,还有每页显示的记录条数pageSize,第一个数字可以动态的获取吗?

  • startIndex = (pageNum - 1) * pageSize

所以,标准通用的mysql分页SQL:

复制代码
select 
  * 
from 
  tableName ...... 
limit 
  (pageNum - 1) * pageSize, pageSize

使用mybatis应该怎么做?

模块名:mybatis-012-page

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;

import java.util.List;

public interface CarMapper {

 
    /**
     * 分页查询
     * @param startIndex 起始下标。
     * @param pageSize 每页显示的记录条数
     * @return
     */
    List<Car> selectByPage(@Param("startIndex") int startIndex, @Param("pageSize") int pageSize);
}

    <select id="selectByPage" resultType="Car">
        select * from t_car limit #{startIndex},#{pageSize}
    </select>

    @Test
    public void testSelectByPage(){
        // 获取每页显示的记录条数
        int pageSize = 3;
        // 显示第几页:页码
        int pageNum = 2;
        // 计算开始下标
        int startIndex = (pageNum - 1) * pageSize;

        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectByPage(startIndex, pageSize);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

2.PageHelper插件

使用PageHelper插件进行分页,更加的便捷。

第一步:引入依赖

复制代码
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.3.1</version>
</dependency>

第二步:在mybatis-config.xml文件中配置插件

typeAliases标签下面进行配置:

复制代码
<plugins>
  <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

第三步:编写Java代码

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;

import java.util.List;

public interface CarMapper {

    /**
     * 查询所有的Car,通过分页查询插件PageHelper完成。
     * @return
     */
    List<Car> selectAll();

    <select id="selectAll" resultType="Car">
        select * from t_car
    </select>

    @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]}
         */
    }

分页信息

复制代码
PageInfo{
  pageNum=2, pageSize=2, size=2, startRow=3, endRow=4, total=6, pages=3, 
  list=Page{count=true, pageNum=2, pageSize=2, startRow=2, endRow=4, total=6, pages=3, reasonable=false, pageSizeZero=false}
  [Car{id=86, carNum='1234', brand='丰田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油车'}, 
  Car{id=87, carNum='1234', brand='丰田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油车'}], 
  prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, 
  navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]
}

四、MyBatis的注解式开发

mybatis中也提供了注解式开发方式,采用注解可以减少Sql映射文件的配置。

当然,使用注解式开发的话,sql语句是写在java程序中的,这种方式也会给sql语句的维护带来成本。 官方是这么说的:

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

使用注解编写复杂的SQL是这样的:

原则:简单sql可以注解。复杂sql使用xml。

模块名:mybatis-013-annotation

打包方式:jar

依赖:mybatis,mysql驱动,junit,logback

配置文件:jdbc.properties、mybatis-config.xml、logback.xml

pojo:org.example1.pojo.Car

mapper接口:org.example1.mapper.CarMapper

1. @Insert

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;

public interface CarMapper {


    @Insert("insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
    int insert(Car car);

}

    @Test
    public void testInsert(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(null,"6666","丰田霸道",32.0,"2020-11-11","燃油车");
        int count = mapper.insert(car);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

2.@Delete

复制代码
package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.annotations.*;

public interface CarMapper {

    @Delete("delete from t_car where id = #{id}")
    int deleteById(Long id);
}

   @Test
    public void testDeleteById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int count = mapper.deleteById(31L);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

3.

3.@Update

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;

public interface CarMapper {

  

    @Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{guidePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")
    int update(Car car);

    @Test
    public void testUpdate(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(17L,"6666","丰田霸道",32.0,"2020-11-11","燃油车");
        int count = mapper.update(car);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

4.@Select

复制代码
package org.example1.mapper;


import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;

public interface CarMapper {

    @Select("select * from t_car where id = #{id}")

    Car selectById(Long id);

    @Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById(17L);
        System.out.println(car);
        sqlSession.close();
    }
复制代码
    @Select("select * from t_car where id = #{id}")
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "carNum", column = "car_num"),
            @Result(property = "brand", column = "brand"),
            @Result(property = "guidePrice", column = "guide_price"),
            @Result(property = "produceTime", column = "produce_time"),
            @Result(property = "carType", column = "car_type")
    })
    Car selectById(Long id);
相关推荐
zhangpeng4555479401 分钟前
用Java NIO模拟HTTPS
java·https·nio
飞奔的马里奥3 分钟前
30天学Java第九天——线程
java·开发语言
工业互联网专业10 分钟前
基于springboot+vue的秦皇岛旅游景点管理系统
java·vue.js·spring boot·毕业设计·源码·课程设计·旅游景点管理系统
畅云客38 分钟前
Apache与Nginx网站压测对比
java·nginx·apache
风吹草1 小时前
java程序乱码问题
java·编码方式
落沐萧萧1 小时前
Java利用无外网(下):ClassPathXmlApplicationContext的不出网利用
java·开发语言
写bug写bug1 小时前
Java并发编程:本质上只有一种创建线程的方法
java·后端
十秒耿直拆包选手1 小时前
spring:xml方式调用构造方法创建Bean,调用set方法配置字段
xml·java·spring
码农新猿类1 小时前
Java EE期末总结(第六章)
java·java-ee
新生农民1 小时前
最小覆盖子串
java·数据结构·算法