MyBatis笔记(尚硅谷笔记)

Mybatis中文官方文档:https://mybatis.org/mybatis-3/zh/index.html

HelloWorld:

流程:

  • 1.根据xml配置文件(全局配置文件:有数据源一些运行环境信息)创建一个SqlSessionFactory对象

  • 2.sql映射文件,配置每一个sql,以及SQL的封装规则等,

  • 3.将sql映射文件注册在全局配置文件中

  • 4.写代码
    1).根据全局配置文件得到SqlSessionFactory
    2).使用sqlSession工厂,获取sqlSession对象使用他来执行增删改查
    一个sqlSession代表着一次和数据库的一次会话,用完要关闭
    3).使用sql的唯一标识来告诉Mybatis执行那个sql,sql都是保存在
    1.加入Mybatis对应的jar包:(我的是Maven)

  <!--mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.4</version>
    </dependency>
    <!--druid-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.21</version>
    </dependency>
    <!--mysql-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.19</version>
      <scope>runtime</scope>
    </dependency>;https://mybatis.org/mybatis-3/zh/index.html

2.创建MyBatis的配置文件,并创建好test类来创建sqlSessionFactory
在这里插入图片描述

 @Test
    public  void test() throws IOException {
        String resource = "MyBatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取sqlSession实例,能直接执行已经映射的sql语句
        /*sqlSession有两个参数,第一个为sql的唯一标识符,也即是id
                               第二个为执行sql的参数

         */
        SqlSession sqlSession = sqlSessionFactory.openSession();
        Employee o = sqlSession.selectOne("com.Mybatis.EmployeeMapper.selectEMP", 1);

        System.out.println(o);
        sqlSession.close();

    }
注意:Mybatis的配置文件中的mapperr节点中一定要对应sql的映射文件

MyBatis接口式编程:

MyBatis为了方便使用者,提供了一种接口式编程:
步骤:
1.创建对应的接口:

package COM.dao;

import COM.bean.Employee;

public interface EmployeeMapperDap {

    public Employee getEmpById(Integer id);
}

2.在MyBatis的sql映射文件调整代码,调整名称空间,和标签的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="COM.dao.EmployeeMapperDap">
<!--
     namespace:名称空间
     id:唯一标识
     resultType:返回值类型
     #{id},从传递过来的参数中取出id值
-->
    <select id="getEmpById" resultType="COM.bean.Employee">
        select id,last_name lastname,email,gender from tbl_employee where id = #{id}
    </select>
</mapper>

3.使用即可:

    @Test
    public void test2() throws IOException { 
        //1.获取sqlSessionFactory
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsStream);

        //2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //获取接口的实现类对象
        //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
        EmployeeMapperDap mapper = sqlSession.getMapper(EmployeeMapperDap.class);
      try {
        Employee empById = mapper.getEmpById(1);
          System.out.println(mapper.getClass());
        System.out.println(empById);
      }finally {
          sqlSession.close();
      }


    }
}

引入外部配置文件:

<!--    使用properties来引入外部文件-->
    <properties  resource="db.properties"></properties>

运行时行为设置:

在这里插入图片描述
补充,驼峰命名法的规则是通过bean的getter setter方法名来判定的.

typealiases(别名处理器)

在这里插入图片描述
本身package指定的包,应该是类名小写,但是别名不区分大小写
在这里插入图片描述实际代码:

<typeAliases>
        <!--   typeAliases:为某个Java类型起别名
                           type:指定要起别名的类型全类名,默认别名就是类名小写
                           alias:指定新的别名

               -->


        <!--单一起别名-->
       <!--<typeAlias type="COM.bean.Employee" alias="emp"></typeAlias>-->


        <!--批量起别名:
              package:可以为某个包下的所有类批量起别名
              name:指定报名(为当前包以及下面所有的后带包的每一个都器一个默认别名(类名小写))
              批量起别名的情况下,可以使用@alias()为一个类单独且别名,为了防止类名冲突
              -->

        <package name="COM.bean"/>
    </typeAliases>
<?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.dao.EmployeeMapperDap">
<!--
     namespace:名称空间
     id:唯一标识
     resultType:返回值类型
     #{id},从传递过来的参数中取出id值
-->
    <select id="getEmpById" resultType="emp">
        select id,last_name,email,gender from tbl_employee where id = #{id}
    </select>
</mapper>

typeHandlers(类型处理器):

在这里插入图片描述在这里插入图片描述

plugins(插件):

在这里插入图片描述

environment(环境):

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

<!-- 4.environments环境,mybatis可以配置多种环境,通过default填入字节点environment的id来设置当前的环境
          environment:配置一个具体的环境信息
              必须具备的两个子节点:id表示当前环境的唯一标识
                       transactionManager:事务管理器
                              type:事务管理器的类型
                                   在mybatis有两种JDBC和MANAGED
                                   自定义事务管理器:实现TransactionFactory接口,type指定为全类名
           DataSource 数据源 :
                   type数据源类型:支持UNPOOLED(非连接池)|POOLED(连接池)|JNDI
                   自定义数据源:实现DataSourceFactory接口,type是全类名
            -->
    <environments default="development">
       <!-- <environment id="test">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

databaseProvider:

在这里插入图片描述
1.步骤:
在你的MyBatis的配置文件中配置databseIdProvider:

<!--databaseIdProvider:支持多数据库厂商
              type="DB_VENDOR" VendorDatabaseIdProvider
              作用就是得到是数据库厂商的标识,mybatis就能根据数据库厂商标识执行不同sql

-->
    <databaseIdProvider type="DB_VENDOR">
        <property name="MySQL" value="mysql"/>
<!--MySQL表示mysql数据库的表示,value表示获取标识后起别名-->
    </databaseIdProvider>
<!--将我们写好的sql映射文件一定要注册到全局配置文件中-->
在mapper文件中加入属性 databaseId 告知运行环境
  <select id="getEmployee" resultType="employee" databaseId="mysql">
        select * from tbl_employee where id=#{id}
    </select>

6.mappers:将sql映射注册到全局配置中
在这里插入图片描述

Class属性:

 <mappers>

<!--      mapper:注册一个sql映射
               resource:引用类路径下的sql映射文件
               url:引用网路径或磁盘路径下的文件
               注册接口:
               class:两种方法
                     1.引用(注册)接口:映射文件必须和接口同名,并且放在与接口同一目录下:
                     2.没有sql映射文件,所有的sql都是利用注解写在接口上
                     推荐:比较重要的Dao接口我们来写sql映射文件
                          不重要的:简单的Dao接口为了开发可以使用快速接口
-->
        <mapper  resource="MyBatisMapper/EmployeeMapper.xml"/>
<!--        <mapper class="COM.dao.daoMappersAnnotation.EmployeeMapperDaoAnnotation"></mapper>-->
<!--    批量注册-->
<!--        <package name="COM.dao"/>-->
    </mappers>

相当于,创建了一个不需要mapper映射文件的或者说需要一个简单的快速接口,需要时使用class属性:
第一种.注解在class填入接口路径,mapper和mapper映射文件在一个包内
在这里插入图片描述第二种.使用注解即可,
在这里插入图片描述在这里插入图片描述

Packae标签:

在这里插入图片描述
接口必须和mapper在同一目录下,便于访问mapper映射的sql文件

MyBatis映射文件

在这里插入图片描述
在这里插入图片描述

基本步骤:
1.在你的接口上定义增删改查的方法:

package COM.dao;

import COM.bean.Employee;

public interface EmployeeMapperDao {

    public Employee getEmpById(Integer id);

    public void addEmpById(Employee employee);

    public void updateEmpById(Employee employee);

    public long deleteEmpById(Integer id);

}

2.在你的sqkl映射文件加入sql语句并且匹配对应方法

<?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.dao.EmployeeMapperDao">
<!--
     namespace:名称空间
     id:唯一标识
     resultType:返回值类型
     #{id},从传递过来的参数中取出id值
-->
    <select id="getEmpById" resultType="employee" databaseId="mysql">
        select id,last_name,email,gender from tbl_employee where id = #{id}
    </select>


    <insert id="addEmpById"  databaseId="mysql" parameterType="employee">
        insert into tbl_employee(last_name,gender,email)
        values (#{lastname},#{gender},#{email})
    </insert>

    <delete id="deleteEmpById" databaseId="mysql" >
    delete  from tbl_employee where id=#{id}

    </delete>

    <update id="updateEmpById" databaseId="mysql" parameterType="employee">
          update tbl_employee set last_name=#{lastname},email=#{email},gender=#{gender} where id=#{id}
    </update>
</mapper>

3.然后就可以使用了


     /*
     *
     * 1.MyBatis允许增删改查直接(在接口上面)定义一下类型返回值:integer,long:返回执行了多少行
   
    boolean:返回执行是否成功
     * 2.我们需要手动提交数据
     *
     * */
     @Test
    public void test() throws IOException {

         InputStream resourceAsStream = Resources.getResourceAsStream(resource);

         SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);

         SqlSession sqlSession = build.openSession();

         EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

         Employee employee=new Employee(1,"a","1","c@qq.ciom");

         mapper.deleteEmpById(1);

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

     }
}

需要注意的是mybatis不会自动提交所以在你的接口实现类完成操作后,要让sqlsession提交:

在这里插入图片描述
2.mybatis会自动提方法包装返回值,只需要在你的接口定义方法的时候定义好返回值即可,返回值可以是 long integer Boolean:
在这里插入图片描述

获取自增主键的值:

在这里插入图片描述

在这里插入图片描述

通过两个属性来获取:

<!--    parameterType表示参数类型,一般可以省略
        mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGeneratedKeys
        parameterType="true",使用自增主键获取主键值策略
        keyProperty="id":指定对应的主键属性,也就是mybatis获取到主键值以后,把这个值封装给javaBean的那个属性
-->
    <insert id="addEmpById" useGeneratedKeys="true" keyProperty="id" databaseId="mysql" parameterType="employee">
        insert into tbl_employee(last_name,gender,email)
        values (#{lastname},#{gender},#{email})
    </insert>

会通过,mybatis也是利用statement.getGeneratedKeys方法来,传入到(当前的填入的id)bean对象中
在这里插入图片描述

获取非自增主键的值:

在这里插入图片描述

MyBatis参数处理:

单个参数:
mybatis不会做特殊处理
#{参数名},取出参数值
在这里插入图片描述红色框子填什么都可以,因为你只传入了一个参数

多个参数:
mybatis会做特殊处理,多个参数会被封装成一个map
key:param1,param2,param3.或者参数索引也可以
value:传入参数值

出现异常

Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
  • 操作:
    方法:
    public Employee getEmpByIdAndLastName(Integer id,String name);
   取值:#{id} #{lastname}

对应的mapper

<!--俩个参数  public Employee getEmpByIdAndLastName(Integer id,String name);
-->
    <select id="getEmpByIdAndLastName" databaseId="mysql">
        select * from tbl_employee where id=#{id} and last_name=#{last_name}
    </select>

命名参数:明确指定封装参数时map的key
在这里插入图片描述多个参数会被封装成一个map
key:使用@Param注解指定的值
value:参数值
#{指定的key}取出对应的参数值

注意:@Param(“id”)这里的id 对应的是#{id}中的id

Pojo&&Map&&To:

Pojo

如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo
#{属性名}:取出出入的pojo的属性值

例子:

对应接口
    public boolean updateEmpById(Employee employee);
对应mapper
 <update id="updateEmpById" databaseId="mysql" parameterType="employee">
          update tbl_employee set last_name=#{lastname},email=#{email},gender=#{gender} where id=#{id}
    </update>
Map

如果多个参数不是我们业务模型的数据,没有对应的pojo,为了方便,我们也可以传入map

例子:

对应接口
    public Employee getEmpByIdAndLastMap(Map<String ,Object> map);
方法    
 @Test
     public void test2() throws IOException {

          InputStream resourceAsStream = Resources.getResourceAsStream(resource);

          SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
          SqlSession sqlSession = build.openSession();

          EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

          Map a=new HashMap();
          a.put("id", 1);
          a.put("lastname", "c");

          Employee empByIdAndLastMap = mapper.getEmpByIdAndLastMap(a);

          System.out.println(empByIdAndLastMap);


          sqlSession.close();
     }
对应映射:
<!--    参数处理pojo map-->
    <select id="getEmpByIdAndLastMap" resultType="employee" databaseId="mysql">
         select * from tbl_employee where id=#{id} and last_name=#{lastname}
    </select>
To

如果多个参数不是业务模型中的数据,但是经常要使用,推荐写一个TO(Transfer Object)数据传输对象
Page{
int index;
int size;
}

思考:

 public Employee GetEmp(@Param("id") Integer id,String lastName);在映射文件中怎么赋值
     
      取值:id-->#{id/param1} last_name-->#{param2}
 
 public Employee GetEmp( Integer id,Employee emp);在映射文件中怎么赋值
     
      取值:id-->#{id/param1}     last_name-->#{param2.lastname}

 public Employee GetEmp( Integer id,@Param("em") Employee emp);在映射文件中怎么赋值
    
      取值:id-->#{id/param1}     last_name-->#{param2.lastname/em.lastname}           

 特别注意,如果是Collection类型(list,set)类型或者数组。会特殊处理,会把list或者数组封装进map中
                     如果key是Collection(collection)List(list)
                           是数组(array)
 
 public Employee GetEmp(List<Integer> ids);在映射文件中怎么赋值
 
      取值:id-->#{list[0]}    

参数值的获取:

测试
select * from tbl_employee where id=${id} and last_name=#{lastname}

结果
select * from tbl_employee where id=1 and last_name=?
#{}和${}的区别:

  • #{}:以预编译的形式,将参数设置到sql语句中:PreparedStatement,防止sql注入
  • ${}:取出的值直接拼装在sql语句中:会有安全问题
  • 大多情况下,我们都应该#{}来取值
  • 当原生jdbc不支持占位符的时候我们可以使用${}进行取值
    比如分表:按照年份分表来拆分
    select * from ${year}_salary where xxx;
    select * from ${year}_salary order by ${f_name};
    例如:
    现在map中加入键值对(表名)
    在这里插入图片描述

在mapepr的select标签使用${}:
在这里插入图片描述

#{}其他用法:

在这里插入图片描述
在这里插入图片描述
jdbcType通常需要在某种特定的条件下被设置
在我们数据为null的时候,有些数据库不能识别mybatis对null的默认处理,比如Oracle(报错)
JdbcType OTHER:无效类型,因为mybatis对所有的null所映射的是原生JDBC的 OTHER oracle不接受
原因:在全局配置汇总。jdbcTypeForNULL=OTHER Oracle不接受
解决办法:
1.设置jdbcType

       <select id="getEmpByIdAndLastMap" resultType="employee" databaseId="mysql">
         select * from tbl_employee where id=${id,jdbcType=NULL} and last_name=#{lastname}
    </select>

2.修改全局配置 :
在这里插入图片描述

select元素:

返回值为list的时候:
你的mapper的resultType不需要填入list,只需要填入基本类型即可:

  • public List getEmpsByLastName(String lastName);
    在这里插入图片描述返回值为Map的时候:
    1.返回一条记录的map:
    key就是列名,值就是对应的值:
    返回值为一条map,MyBatis自动将返回的employee的列名和值封装进map中
接口名:
//    返回一条记录的map:key就是列名,值就是对应的值:
    public  Map<String,Object> getEmpByIdReturnMap(Integer id);


对应mapper:
<!--    返回值为一条map,MyBatis自动将返回的employee的列名和值封装进map中-->
    <select id="getEmpByIdReturnMap" resultType="map" >
                select * from tbl_employee where id=#{id}

    </select>

运行结果:在这里插入图片描述
2.返回多条记录的map
多条记录封装一个map,Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean

接口:
//     返回多条记录的map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
     @MapKey("id")
//    告诉mybaits封装这个map的时候那个属性作为主键
    public Map<Integer,Employee> getEmpsByLastNameReturnMap(String LastName);
对应的mapper:
<!--   返回多条记录的map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean-->
    <select id="getEmpsByLastNameReturnMap" resultType="employee" >
                select * from tbl_employee where last_name like #{lastname}
    </select>

运行结果在这里插入图片描述

自定义结果映射:

在这里插入图片描述

<!--  自定义某个javaBean的封装规则
        type:自定义规则的Java类型
         id:唯一id方便引用
-->
    <resultMap id="MyEmp" type="COM.bean.Employee">
        <id column="id" property="id"></id>
        <!--指定主键列的封装规则:
        id定义主键会底层优化
        column:指定一列对应property
        property:指定对应的javaBean属性
-->
<!--        定义普通列封装规则-->
        <result column="last_name" property="lastname"></result>
<!-- 其他不指定的列会自动封装-->
    </resultMap>
    
<!--    resultMap:自定义结果集映射规则-->
    <select id="getEmpById" resultMap="MyEmp" >
        select * from tbl_employee where id = #{id}
    </select>

关联查询:

配置你的外键,以及对应的类:
配置好的表
在这里插入图片描述

Employee类:
在这里插入图片描述
对应的department类
在这里插入图片描述

配置你的map

<resultMap id="MyEmpAndDept" type="employee">
        <id column="id" property="id"></id>
        <!--指定主键列的封装规则:
        id定义主键会底层优化
        column:指定一列对应property
        property:指定对应的javaBean属性
-->
        <!--定义普通列封装规则-->
<!--联合查询:级联属性封装结果来-->
注意:这里的dept是javabean Empployee的对应department的属性名
        <result column="last_name" property="lastname"></result>
        <result column="gender" property="gender"></result>
        <result column="d_id" property="dept.id"></result>
        <result column="dept_name" property="dept.departmentName"></result>

    </resultMap>
    
    <select id="getEmpAndDept" resultMap="MyEmpAndDept" >
      select a.id,a.gender,a.last_name,a.email,a.d_id,b.dept_name from tbl_employee a,tbl_depart b where a.d_id=b.id and a.id=#{id}
    </select>

association:
在这里插入图片描述

<!--association:-->

    <resultMap id="MyDifEmp" type="employee">
    <!--  association可以指定联合的javaBean对象
                 dept:指定那个对象是联合的对象
                 javaType:指定这个属性指定的类型(不可以省略)
    -->
        <result column="last_name" property="lastname"></result>
        <result column="gender" property="gender"></result>
        <association property="dept" javaType="department">
<!--            这里的id指的是department里的id-->
            <id column="d_id" property="id"></id>
            <id column="dept_name" property="departmentName"></id>
        </association>
    </resultMap>



    <select id="getEmpAndDept" resultMap="MyDifEmp" >
      select a.id,a.gender,a.last_name,a.email,a.d_id,b.dept_name from tbl_employee a,tbl_depart b where a.d_id=b.id and a.id=#{id}
    </select>

分布查询:
步骤:
1.构建思路:
使用association进行分布查询:
1.先按员工id查询员工信息
2.根据查询员工信息中的d_id值去部门表查出部门信息
3.部门设置到员工中
2.创建department表对应查询的mapper和接口:
在这里插入图片描述
在这里插入图片描述
然后在另一个mapper配置association:
在这里插入图片描述注意:图中select:一定要对应接口的方法名,路径写全
新加的mapper要加入的Mybatis.
延迟加载:
延迟加载:
Employee==>Dept
我们每次查询Employee对象的时候,都将一起查询出来
要求:部门信息只在我们使用的时候在查询
方法:
在分布查询的基础上加上两个配置
lazyLoadingEnabled:我们需要什么加载什么
aggressiveLoading:我们需要任何一个或多个 直接全部加载

    <settings>
<!--    延迟加载     -->
<!--        lazyLoadingEnabled:要什么给什么
             aggressiveLazyLoading:要一个全都给
               -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

    </settings>

collection定义封装规则:

问题:当我们需要通过一个department来给我们employee的集合,我们该怎么做?
思考:我们需要通过部门表的depid 来做文章:

sql语句:select b.id did,b.dept_name dn,a.id eid,a.last_name ln,a.gender gender
      from tbl_depart b
      left join tbl_employee a
      on b.id=a.id
      where b.id=#{id}
在你的deparment类中创建list
对应的mapper:

在这里插入图片描述
collection的分布查询:(继上一个方法)
大体与association的意思差不多:
department与employee的方法接口:

 public Department getDeptByIdStep(Integer id);

public List<Employee> getDeptByIdStep(Integer id);

对应的mapper:
在这里插入图片描述

在这里插入图片描述拓展:collection和association中的分布查询,当我们需要传入多个参数时:

 当分布查询,需要传入多列的时候
         将多列的值分装成map传值
         column="{key1=value1,key1=value1}"
         注意:key一定要对应#{这里的值} 例如:#{a} key就是a
         fetchType=lazy:表示使用延迟加载
         fetchType=eager:表示使用立即加载
 对应的mapper:
 
 <resultMap id="MyDeptByIdStep" type="department">
           <id column="id" property="id"></id>
           <result column="dept_name" property="departmentName"></result>
        <collection property="employees" select="COM.dao.EmployeeMapperPlus.getDeptByIdStep"
                    column="{xid=id}" fetchType="lazy"
        >

        </collection>
    </resultMap>

discriminator

<!--discriminator:
        鉴别器:mybatis可以使用discriminator判断某列的值,根据某列的值改变封装行为
        封装employee:
              如果查出是女生:就把部门信息查询出来,否则不查询
              如果是男生,就把lastName赋给email
      -->

    <resultMap id="myEmpByDiscriminator" type="employee">
        <id  column="id" property="id"></id>
        <result column="last_name" property="lastname"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <!--
            column:指定判定的列名
            javaType:列值对应的java类型
        -->
        <discriminator javaType="string" column="gender">
<!--    女生resultType:指定封装的结果类型 resultType:不可缺少-->
            <case value="0" resultType="employee">
                <association property="dept" select="COM.dao.DepartmentMapper.getDeptName"
                             column="d_id">
                </association>
            </case>
<!--    男生resultType-->
            <case value="1">
                <id  column="id" property="id"></id>
                <result column="last_name" property="lastname"></result>
                <result column="gender" property="gender"></result>
                <result column="last_name" property="email"></result>            </case>
        </discriminator>
    </resultMap>

    <select id="getDeptByIdDiscriminator" resultMap="myEmpByDiscriminator" >
      select * from tbl_employee where id=#{id}
    </select>

动态sql:

  • 动态SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作。
  • 动态SQL 元素和使用JSTL 或其他类似基于XML 的文本处理器相似。
  • MyBatis 采用功能强大的基于OGNL 的表达式来简化操作。
    –if
    –choose (when, otherwise)
    –trim (where, set)
    –foreach
    if:

在这里插入图片描述
小技巧:
查询的时候如果某些条件没带sql拼装会有问题
1.给where后面加上1=1,以后的条件都and xx
在这里插入图片描述

2.mybatis使用where标签来将所有的查询条件包括在内,mybatis的where会将sql语句中的or and删除
这个where只会去掉第一个where
在这里插入图片描述trim(自定义字符创截取):

<!--
   当sql语句 后面多出and or的时候 ,where不可以解决
    Trim(自定义字符串截取)的属性:
     prefix="":前缀,trim标签体中是整个字符拼串后的结果
               prefix给拼串后trim标签体的整个加一个前缀
     prefixOverrides="" 前缀覆盖,表示去掉整个字符串前面多余的字符
     suffix="" 后缀 suffix给拼串后trim标签体的整个加一个后缀
     suffixOverrides="" 后缀覆盖,表示去掉整个字符串前面多余的字符

-->
    <select id="getEmpByConditionTrim" resultType="employee">
               select * from tbl_employee
             <trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="and">
                <if test="id!=null">
                    id =#{id} and
                </if>

                <if test="lastname!=null and lastname!=&quot;&quot;">
                     last_name like #{lastname} and
                </if>

                <if test="email!=null and email.trim()!=&quot;&quot;">
                     email = #{email} and
                </if>

                <if test="gender==0 or gender==1">
                     gender = #{gender}
                </if>
             </trim>
    </select>

choose(分支选择)

<select id="getEmpByConditionChoose" resultType="employee">
         select * from tbl_employee
         <where>
             <!--   如果带了id 查id ...-->
                <choose> 相当于switch
                
                    <when test="id!=null"> 相当于case
                        id=#{id}
                    </when>

                    <when test="lastname!=null">
                        last_name like #{lastname}
                    </when>

                    <when test="email!=null">
                        last_name like #{lastname}
                    </when>

                   <otherwise>  就是otherwise
                       gender=0
                   </otherwise>
                </choose>
         </where>
    </select>

set与if的动态更新:
可以让帮助我们把,去除

 <update id="updateEmp">
    update tbl_employee
<!--   Set:标签的使用-->
<!--    <set>-->
<!--        <if test="lastname!=null">-->
<!--              last_name=#{lastname},-->
<!--        </if>-->

<!--        <if test="email!=null">-->
<!--            email=#{email},-->
<!--        </if>-->

<!--        <if test="gender!=null">-->
<!--            gender=#{gender},-->
<!--        </if>-->
<!--    </set>-->


    <!--Trim-->
    <trim prefix="set" suffixOverrides=",">

        <if test="lastname!=null">
                      last_name=#{lastname},
        </if>

        <if test="email!=null">
                    email=#{email},
        </if>

        <if test="gender!=null">
                    gender=#{gender},
        </if>

    </trim>
        <where>
            id=#{id}
        </where>
    </update>

foreach:
在这里插入图片描述
foreach下的批量查询:

首先在你的方法对参数命名 ,以便于取值
//通过foreach的使用,来批量保存
    public void addEmpsByForeach(@Param("emps") List<Employee> emps);

然后:
<!--批量保存-->
<!--    方法一-->
<!--    mysql下批量保存,可以foreach遍历 mysql支持values(),()语法-->
<!--        <insert id="addEmpsByForeach" >-->
<!--            insert into tbl_employee (last_name,gender,email,d_id)-->
<!--            VALUES-->
<!--            <foreach collection="emps" item="emp"  separator=",">-->
<!--                (#{emp.lastname},#{emp.gender},#{emp.email},#{emp.dept.id})-->
<!--            </foreach>-->
<!--        </insert>-->
<!--方法二-->
     <insert id="addEmpsByForeach" >
         <foreach collection="emps" item="emp"  separator=";">
            insert into tbl_employee (last_name,gender,email,d_id)
           VALUES
            (#{emp.lastname},#{emp.gender},#{emp.email},#{emp.dept.id})
        </foreach>
     </insert>


两个参数( parameter和databaseId):

  两个内置参数:
         不只是方法转递过来的参数可以被用来判断,取值...
         mybatis默认还有两个那内置参数
            parameter:代表整个参数
                     单个参数:_parameter就是这个参数
                     多个参数:参数会被封装为一个map:_parameter就是代表这个map
            databaseId:如果配置了DatabaseProvider的标签
                     那么_databaseId就有值
-->
    <select id="getEmpTestPara" resultType="employee">
        <if test="_databaseId='mysql'">
            select * from tbl_employee
           <if test="_parameter!=null"></if>
             where last_name =#{_parameter.lastname} and d_id=#{_parameter.did}
        </if>
    </select>


传入多个参数
<select id="getEmployeeByInnerParam" resultType="employee">
        <if test="_databaseId=='mysql'">
            <if test="_parameter!=null">
        select  * from tbl_employee where id=#{_parameter.param1} and last_name like #{_parameter.param2}
            </if>
        </if>
    </select>
    

Bind:
注意:
需求:我们模糊查询的时候,不需要在打入%
方法
在这里插入图片描述
这样当然可以,因为${}是将sql语句拼起来吗,但是会出现sql注入问题,所以我们选择bind
在这里插入图片描述sql抽取可重复的sql语句:

    <select id="getEmpTestBind" resultType="employee">
        select
        <!--include标签用来引用外部标签-->
        <include refid="insertColumn">

        </include>
        from tbl_employee
            <if test="_parameter!=null">
             <bind name="_lastname" value="'%'+lastname+'%'"/>
                where last_name like #{_lastname}
            </if>

    </select>

<!--
   sql标签:
       抽取可重用的sql片段,方便后面引用
          1.我们经常使用到这个标签,将要查询的列名,或者插入用的列明抽取出来方便引用
          2.include来引用已经抽取到的sql
               可以自定义属性,sql可以在内部适用:用法就是 ${} ,#{}不可以使用
               例如:
                       <include refid="insertColumn">
                            <property name="testColumn" value="depatName"/>
                       </include>

                       对应的sql标签:
                        <sql id="insertColumn" >
                            * ${testColumn}
                        </sql>

-->

    <sql id="insertColumn" >
        *
    </sql>

缓存

一级缓存(本地缓存):sqlSession级别的缓存,一级缓存是一直开启的

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中,sqlSession级别的缓存,一级缓存是一直开启的
  • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询。
    例子:
 /*
    * 两级缓存:
    *     一级缓存:(本地缓存)sqlSession级别的缓存,一级缓存是一直开启的,sqlSession级别的缓存,一级缓存是一直开启的
    *               与数据库同一次会话期间查询到的数据会放在本地缓存中
    *               以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询。
    *     二级缓存:(全局缓存)
    * */
    @Test
    public void testFirstLevelCache(){

        EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper.getEmpById(1);

        System.out.println(empById);

        //比如,当你查询了一次,你还需要再次查找一次,在传统的JDBC中,我们需要在监理一次会话等

        Employee empById1 = mapper.getEmpById(1);
        System.out.println(empById1);
        sqlSession.close();


    }

注意:这里的运行结果
在这里插入图片描述
虽然我们查了两次,但是,我们只用了一个会话,查询语句是一样的,所以我们只用了一次会话
一级缓存失效的情况:
条件:

  • 1.sqlSession不同,代表两次不同的会话
 @Test
    public void testSecondLevelCache(){

        EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper.getEmpById(1);

        System.out.println(empById);

        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        EmployeeMapperDao mapper1 = sqlSession2.getMapper(EmployeeMapperDao.class);

        Employee empById1 = mapper1.getEmpById(1);

        System.out.println(empById==empById1);


    }

运行结果:
在这里插入图片描述

  • 2.sqlSession相同,但查询条件不一样(一级缓存 没有上一次的数据)
 @Test
    public void testSecondLevelCache(){

        EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper.getEmpById(1);

        System.out.println(empById);

        Employee empById1 = mapper.getEmpById(2);
        
        System.out.println(empById==empById1);


    }

结果:
在这里插入图片描述

  • 3.sqlSession相同,但两次查询之间,增加增删改操作
    @Test
    public void testSecondLevelCache(){

        EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper.getEmpById(1);

        System.out.println(empById);

       //3.sqlSession相同,但两次查询之间,增加增删改操作

        mapper.addEmpById(new Employee(null,"giaoge", "0", "654@qq.com0"));

        System.out.println("add Success");

        Employee empById1 = mapper.getEmpById(1);

        System.out.println(empById==empById1);




    }
  • 4.sqlSession相同,但手动清除了缓存
    @Test
    public void testCacheUnSuccess(){

        EmployeeMapperDao mapper = sqlSession.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper.getEmpById(1);

        System.out.println(empById);

//      4.sqlSession相同,但手动清除了缓存
        sqlSession.clearCache();
        Employee empById1 = mapper.getEmpById(1);

        System.out.println(empById==empById1);

    }

理解:说白了就是一个sqlSession的map,根据sql来判别
二级缓存:(全局缓存):基于namespace级别的缓存,一个namespace代表一个二级缓存
工作机制:
1.一个会话:查询一条数据,这个数据就会被放在当前会话的一级缓存中
2.如果会话关闭后,对应的一级缓存就会保存到二级缓存中,新的会话查询信息,就可以参照二级缓存
3.一个namespace对应一个二级缓存 ,不同namespace查出的数据会放在自己的Map
使用:在这里插入图片描述
cache属性:

  • eviction=“FIFO”:缓存回收策略
    •LRU –最近最少使用的:移除最长时间不被使用的对象。
    •FIFO –先进先出:按对象进入缓存的顺序来移除它们。
    •SOFT –软引用:移除基于垃圾回收器状态和软引用规则的对象。
    •WEAK –弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    •默认的是LRU。
  • flushInterval:刷新间隔,单位毫秒
    •默认情况是不设置,也就是不清空
  • size:引用数目,正整数
    •代表缓存最多可以存储多少个对象,太大容易导致内存溢出
  • readOnly:只读,true/false
    •true:只读缓存;会将数据的引用交给用户,说白了,速度快,不安全
    •false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
  • type:指定自定义的缓存的全类名
    /*二级缓存:(全局缓存):
            二级缓存:(全局缓存):基于namespace级别的缓存,一个namespace代表一个二级缓存**
                    工作机制:
                              1.一个会话:查询一条数据,这个数据就会被放在当前会话的一级缓存中
                              2.如果会话关闭后,对应的一级缓存就会保存到二级缓存中,新的会话查询信息,就可以参照二级缓存
                              3.一个namespace对应一个二级缓存 ,不同namespace查出的数据会放在自己的Map
                       注意:数据会从二级缓存查找的前提。是上一个sqlSession必须关闭
                            二级缓存生效的前提 ,sqlSession关闭,一级缓存才会将数据提交到二级缓存中
                       (默认顺序:一级缓存---(这个sqlSession提交或关闭)二级缓存)
                  使用:
                        1.开启全局二级缓存配置:在mybatis的全局变量配置         <setting name="cacheEnabled" value="true"/>
                        2.去mapper.xml中配置使用二级缓存
                                <cache></cache>
                                cache标签的属性:
					                            eviction=“FIFO”:缓存回收策略
					                                •LRU –最近最少使用的:移除最长时间不被使用的对象。
					                                •FIFO –先进先出:按对象进入缓存的顺序来移除它们。
					                                •SOFT –软引用:移除基于垃圾回收器状态和软引用规则的对象。
					                                •WEAK –弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
					                                •默认的是LRU。
					                           flushInterval:刷新间隔,单位毫秒
					                                •默认情况是不设置,也就是不清空
					                           size:引用数目,正整数
					                                •代表缓存最多可以存储多少个对象,太大容易导致内存溢出
					                           readOnly:只读,true/false
					                                •true:只读缓存;会将数据的引用交给用户,说白了,速度快,不安全
					                                •false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
					                           type:指定自定义的缓存的全类名
                        3.我们的POJO需要实现序列化

    */

    @Test
    public void SecondLevelCacheTest(){

        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        EmployeeMapperDao mapper1 = sqlSession1.getMapper(EmployeeMapperDao.class);
        EmployeeMapperDao mapper2 = sqlSession2.getMapper(EmployeeMapperDao.class);

        Employee empById = mapper1.getEmpById(1);
        System.out.println(empById);

        sqlSession1.close();

        //注意:这里的第二次查询是从二级缓存中拿到的数据,并没有发送新的sql
        Employee empById2 = mapper2.getEmpById(1);
        System.out.println(empById2);

        sqlSession2.close();

        System.out.println(empById==empById2);
    }
  • 和缓存有关的设置/属性:
    1).CacheEnabled=true/false: 表示开启/关闭二级缓存 (一级缓存不可以被关闭)
    2). useCache=true/false: mapper文件中每一个select标签都拥有这个属性,表示使用二/不使用级缓存
    3).flushCache=true: mapper文件中每一个增删改标签都拥有,表示当前这个方法执行完
    毕清除缓存(一级二级全都会被清除)
    4).sqlSession2.clearCache(); 表示只清除当前session的一级缓存
    5).localCacheScope: 本地缓存(一级缓存)作用域:当前会话的所有数据保存在会话缓存中.
    属性值:
    Session:默认值,当前会话使用缓存
    STATEMENT:当前会话没有缓存(手动关闭一级缓存)
    在这里插入图片描述
注意:每次当你使用增删改操作的时候,都会刷新缓存(一级二级)

个人理解: 一级缓存和二级缓存面对的对象是不一样,一级缓存面对的是同一个sqlSession内同一个namespace的操作,二级缓存则是所有sqlSession的不同的namespace的缓存域,所以当你有新的会话时,优先查找二级缓存的
缓存的原理:
在这里插入图片描述
在这里插入图片描述

缓存的顺序: 二级缓存>一级缓存》数据库,原因在上面个人理解和图片

MyBatis逆向工程:

MBG官网:http://mybatis.org/generator/

在这里插入图片描述

MBG运行

对应的配置文件,

<?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>
<!--    <classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />-->
    <properties resource="db.properties"></properties>
<!--    数据库连接-->
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone=UTC"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <javaTypeResolver >
<!--java类型解析器,具体看文档-->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>
<!--指定javaBean生成策略-->
        <javaModelGenerator targetPackage="Bean" targetProject="D:\Code\SSM_Work\MybatisMBG\src\main\webapp\Java">
<!--            targetPackage:目标包
                targetProject:目标工程
-->
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
<!--sql映射文件策略-->
        <sqlMapGenerator targetPackage="Mappers"
                         targetProject="D:\Code\SSM_Work\MybatisMBG\src\main\webapp\Resouorces">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
<!--指定Mapper接口所在位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="Mappers"  targetProject="D:\Code\SSM_Work\MybatisMBG\src\main\webapp\Java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
<!--指定逆向生成的数据库的表,根据表创建javaBean-->
       <table tableName="tbl_employee" domainObjectName="Employee"></table>
        <table tableName="tbl_depart" domainObjectName="Department"></table>
    </context>
</generatorConfiguration>

对应的java运行代码:

    public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File(MBG.class.getClassLoader().getResource("Mbg.xml").getPath());

          ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);

    }

生成成功:
在这里插入图片描述

QBC风格的拼装条件查询

代码

   @Test
    public  void testExample() throws Exception {
        String Resource="mybatis-config.xml";

        InputStream resourceAsStream = Resources.getResourceAsStream(Resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession(true);

        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);

//        查询条件拼装
//     创建一个criteria
        EmployeeExample employeeExample=new EmployeeExample();
       EmployeeExample.Criteria criteria = employeeExample.createCriteria();
//     为你的criteria写上上查询条件
        criteria.andLastNameLike("%e%");
//        criteria.andGenderEqualTo("1");
//        criteria.andDIdIsNull();
//        在通过selectByExample查询
        List<Employee> employees = mapper.selectByExample(employeeExample);

        System.out.println(employees);


    }

在这里插入图片描述

源码分析:

sqlSessionFactory:

在这里插入图片描述

sqlSession:

在这里插入图片描述图中pluginAll方法是用来遍历所有的插件,基于拦截器

getMapper获取接口的代理对象:

在这里插入图片描述

查询流程

在这里插入图片描述总结:

在这里插入图片描述总结:
在这里插入图片描述

插件:

插件在你的每一个四大对象都会遍历,但他只会根据注解来指定绑定,并返回代理对象,对对象进行封装

  1. 编写插件,实现interceptor的接口:
package plugin;


import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Statement;
import java.util.Properties;

/**
     @Intercepts: 表示当前这个类是一个插件
     @Signature: 为插件签名,告诉mybaits当前插件用来拦截哪一个对象的哪一个方法
**/
@Intercepts({
        @Signature(type = StatementHandler.class,method ="parameterize",args = java.sql.Statement.class)
})
public class MyFirstPlugin  implements Interceptor {
/**
    intercept:拦截
              拦截目标对象(四大对象)的某一个方法
 **/

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
//        执行目标方法
        System.out.println("intercept");
        Object proceed = invocation.proceed();


//        返回执行后的返回值
        return  proceed;
    }
//plugin:
//       包装目标对象,包装,为目标对象常见一个代理对象
    @Override
    public Object plugin(Object target) {

        /**
         * Mybatis提供Plugin来为target包装成一个代理对象
         */
        System.out.println("plugin "+target);
        Object wrap = Plugin.wrap(target, this);
        System.out.println(wrap.toString());
        return wrap;
    }

    /**
     *
     * setProperties:
     *           将插件注册时的property属性设置进来,通过mybaits配置文件中plugins,配置,方便上面方法提取
     *
     */
    @Override
    public void setProperties(Properties properties) {

        System.out.println("properties:"+properties);


    }
}

  1. 使用@intercepts完成插件签名

在这里插入图片描述运行:

    }
    /**
     * 1.插件原理:
     *           在四大对象创建的时候
     *            1.每个对象出来的时候不是直接返回的,而是
     *              InterceptorChain.pluginAll(param)
     *            2.获取到所有的Interceptor,并通过plugin方法包装返回target对象
     *            3.插件机制,我们可以使用插件为目标对象创建一个代理对象,AOP
     *
     *2.步骤:
     *       1.编写插件,实现interceptor的接口
     *       2.使用@intercepts完成插件签名
     *       3.在你的Mybatis中,注册你的插件
     * @throws Exception
     */
    @Test
    public void testPlugin() throws IOException {
        String Resource="mybatis-config.xml";

        InputStream resourceAsStream = Resources.getResourceAsStream(Resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession(true);

        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);

        Employee employee = mapper.selectByPrimaryKey(1);

        System.out.println(employee);


    }

注意拦截器每一个对象都会拦截,只不过在你的@Intercepts下面注明:具体为哪一对象产生动态代理,

运行流程:

在这里插入图片描述

PageHelper插件(分页)

中文官网:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

  1. 导入jar包
    <!--分页插件-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.4</version>
    </dependency>

  1. 配置插件:
<!--pageHelper-->
    <plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<!--             -->
        </plugin>
    </plugins>
  1. 使用

    @Test
    public void testPageHelper() throws IOException {

        String Resource="mybatis-config.xml";

        InputStream resourceAsStream = Resources.getResourceAsStream(Resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession(true);

        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
/**
 PageHelper
        Page<Object> objects = PageHelper.startPage(1, 5);

        System.out.println("当前页码"+objects.getPageNum());
        System.out.println("总记录数"+objects.getTotal());
        System.out.println("每页记录数"+objects.getPageSize());
        System.out.println("总页码"+objects.getPages());

 */

        Page<Object> objects = PageHelper.startPage(1, 5);

        List<Employee> emps = mapper.getEmps();
//        NavigateFirstPage表示显示最多页码数
        PageInfo pageInfo=new PageInfo(emps,5);

        System.out.println("当前页码"+pageInfo.getPageNum());
        System.out.println("总记录数"+pageInfo.getTotal());
        System.out.println("每页记录数"+pageInfo.getPageSize());
        System.out.println("总页码"+pageInfo.getPages());
        System.out.println("第一页"+pageInfo.getNavigateFirstPage());
        System.out.println("是否有下一页"+pageInfo.isHasNextPage());
        System.out.println("NavigateFirstPage"+pageInfo.getNavigatepageNums());


        /*
         assertEquals(1, page.getPageNum());
         assertEquals(10, page.getPageSize());
         assertEquals(1, page.getStartRow());
         assertEquals(10, page.getEndRow());
         assertEquals(183, page.getTotal());
         assertEquals(19, page.getPages());
         assertEquals(1, page.getFirstPage());
         assertEquals(8, page.getLastPage());
         assertEquals(true, page.isFirstPage());
         assertEquals(false, page.isLastPage());
         assertEquals(false, page.isHasPreviousPage());
         assertEquals(true, page.isHasNextPage());
         */
        System.out.println(emps);
    }

批量操作:

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>