栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

004 MyBatis教程:

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

004 MyBatis教程:

一、MyBatis简介

1、MyBatis历史

MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github。

iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

2、MyBatis特性
    MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。
    说明1: 定制化sql:指的是sql可以自己编写,不像之前的hibernate框架的sql 是使用框架生成的。
    说明2:高级映射:指的是数据库中的字段和对象的属性不一致时,如何映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
    说明1:底层:封装的是jdbc。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
    说明1:有2种配置方式,其中xml方式用的比较多。MyBatis 是一个 半自动的ORM(Object Relation Mapping)框架。
    说明1:jdbc是一个纯手动的框架。
    说明2:hibernate是一个全自动框架。
    说明3:ORM:对象关系映射,O指的是:java中的实体类对象,R指的是:关系型数据库,M指的是:映射,即:java中的实体类对象和关系型数据库中的数据创建映射关系,每当操作数据库中的数据就像操作实体类对象一样简单。
3、MyBatis下载

MyBatis下载地址:https://github.com/mybatis/mybatis-3

4、和其它持久化层技术对比

JDBC:

    SQL 夹杂在Java代码中耦合度高,导致硬编码内伤维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见代码冗长,开发效率低

Hibernate 和 JPA:(底层封装的都是jdbc)

    操作简便,开发效率高程序中的长难复杂 SQL 需要绕过框架内部自动生产的 SQL,不容易做特殊优化基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。反射操作太多,导致数据库性能下降

MyBatis:(底层封装的都是jdbc)

    轻量级,性能出色SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据开发效率稍逊于HIbernate,但是完全能够接受
二、搭建MyBatis 1、开发环境

IDE:idea 2019.2

构建工具:maven 3.5.4

MySQL版本:MySQL 5.7

MyBatis版本:MyBatis 3.5.7

2、创建maven–java工程 a>打包方式:jar

说明:myBatis框架底层封装的是jdbc,因为访问数据库时,直接通过java代码访问就行了,不需要有服务器的支持,所以打包方式为jar包,创建的是Maven—java项目。

创建过程:略。

b>引入依赖


        
        
            org.mybatis
            mybatis
            3.5.7
        

        
        
            junit
            junit
            4.12
            test
        

        
        
            mysql
            mysql-connector-java
            5.1.3
        
    
3、提供数据库以及表结构

4、提供t_user表对应的实体类

说明:

    普通映射需要保证数据库表中的字段和实体类对象的属性名保持一致,底层用的是反射。高级映射解决的是数据库表中的字段和实体类对象的属性名不一致。
package com.atguigu.mybatis.pojo;


public class User { //set,get,有参构造,无参构造,toString。注意:使用包装类型


    private Integer id;

    private String username;

    private String password;

    private Integer age;

    private String sex;

    private String email;

    public User() {
    }

    public User(Integer id, String username, String password, Integer age, String sex, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                ", age=" + age +
                ", sex='" + sex + ''' +
                ", email='" + email + ''' +
                '}';
    }
}

5、创建MyBatis的核心配置文件
    习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合Spring 之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息核心配置文件存放的位置是src/main/resources目录下




    
    
        
            
            
                
                
                
                
            
        
    
    
    
        
    



6、创建mapper接口

MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。

说明:

    原来的dao需要创建接口以及接口实现类,而现在的Mybatis是面向接口编程,不需要创建其实现类只需要创建其接口即可。当我们通过mybatis的方式去创建Mapper接口对象,然后我们去调用这个接口中的方法,它就会自动匹配一个sql语句并执行。一般一张表对应一个Mapper接口一个映射文件。
package com.atguigu.mybatis.mapper;


public interface UserMapper {
    


    
    int insertUser();


}

7、创建MyBatis的映射文件

相关概念:ORM(Object Relationship Mapping)对象关系映射。

对象:Java的实体类对象关系:关系型数据库映射:二者之间的对应关系

Java概念数据库概念
属性字段/列
对象记录/行

1、映射文件的命名规则:

表所对应的实体类的类名+Mapper.xml例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml因此一个映射文件对应一个实体类,对应一张表的操作MyBatis映射文件用于编写SQL,访问以及操作表中的数据MyBatis映射文件存放的位置是src/main/resources/mappers目录下

2、MyBatis中可以面向接口操作数据,要保证两个一致:

a>mapper接口的全类名和映射文件的命名空间(namespace)保持一致b>mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致





    
    
        insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
    


创建步骤:
方式一:万能方式:右键new—file,这种方式需要指定后缀,并且创建好的映射文件没有头信息。



方式二:在idea中可以设置模板,详情查看目录五。

8、通过junit测试添加功能
package com.atguigu.mybatis.test;

import com.atguigu.mybatis.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;


public class MyBatisTest {

    


    @Test
    public void testMyBatis() throws IOException {
        //加载核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //获取SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //获取sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        //获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //获取mapper接口对象  这个方法底层用的是代理模式,它可以返回接口对应的实现类对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //测试功能
        int result = mapper.insertUser();
        //提交事务 说明:在mybatis-config.xml配置的事务管理方式标签,是以最原始的jdbc
        //            的方式管理事务,所以当前事务的提交和回滚都需要手动处理。
        //sqlSession.commit(); 手动设置提交,缺点:每次执行完增删改后都要手动提交事务,太过麻烦,可以把事务提交设置为自动提交
        //                                                                                   默认是不自动提交。
        System.out.println("result:"+result);
    }



}

SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的 会话)SqlSessionFactory:是“生产”SqlSession的“工厂”。工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的 相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象。

测试:

9、加入log4j日志功能

说明:通过日志功能来检测,我们当前实现的功能所执行的sql。

a>加入依赖


        
            log4j
            log4j
            1.2.17
        
b>加入log4j的配置文件

log4j的配置文件名为log4j.xml,存放的位置是src/main/resources目录下
配置文件的名字是固定的:log4j.xml。





    
        
        
            
        
    
    
        
    
    
        
    
    
        
        
    


日志的级别
FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)
从左到右打印的内容越来越详细

三、MyBatis的增删改查 1、添加

详情查看:二 -----》8 通过junit测试添加功能

2、删除

Mapper接口方法:

    void deleteUser();

映射文件:

 
    
        delete from t_user where id = 5
    

测试类:

 //删除:
    @Test
    public void testCRUD2() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser();//返回值是void,所以不用接收
    }

3、修改

Mapper接口方法:

    void updateUser();

映射文件:


    
        update t_user set username = '张三' where id = 4
    

测试类:

//修改:
    @Test
    public void testCRUD() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser();//返回值是void,所以不用接收
    }

4、查询一个实体类对象

Mapper接口方法:

 
    User getUserById();

映射文件:


    
    
        select * from t_user
    

测试类:

//查询所有的用户信息
    @Test
    public void testCRUD4() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List list = mapper.getAllUser();
        list.forEach(user -> System.out.println(user));
    }
6、查询功能:注意事项

注意:

查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射 关系:

resultType:自动映射,用于属性名和表中字段名一致的情况resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值 四、核心配置文件详解

核心配置文件中的标签必须按照固定的顺序:
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorF actory?,plugins?,environments?,databaseIdProvider?,mappers?






    
    
    
    
        
        
        
        
    
    
    
        

        
        
        
        
    

    
    
       
        
            
            
            
            
                
                
                
                
                
                
                
                
            
        
    
    
    
        
        
        
    
    

1、MyBatis核心配置文件之environments

说明:用来配置多个连接数据库的环境.


    
        
        
            
            
            
            
                
                
                
                
                
                
                
                
            
        

        
            
            
                
                
                
                
            
        
    
2、MyBatis核心配置文件之properties

说明:

    数据库的连接信息直接写在核心配置文件中写死了,可以动态的写在properties文件中,在核心配置文件引入properties文件,之后通过标签取出来。jdbc前缀,一个项目中可能要多个properties配置文件,加上前缀是为了区分不同的properties文件

编写properties文件:
方式一:万能写法,在resources-----右键----new file----jdbc.properties(需要添加后缀)
方式二:不需要添加后缀:

# 说明:jdbc前缀,一个项目中可能要多个properties配置文件,加上前缀是为了区分不同的properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root

把properties文件引入到核心配置文件:

 

    
    

之后通过标签把值取出来:


            
                
                
                
                
                
                
                
                
            
3、MyBatis核心配置文件之typeAliases

说明:映射文件中的查询标签的resultType属性, 需要设置返回值的类型,一般是pojo对象的全类名,查询是最常见的功能每次都要写全类名太麻烦,可以设置别名来代替全类名。

 
    
        
        
        
        
        
    

在映射文件中就可以直接使用别名了,并且不区分大小写。

4、MyBatis核心配置文件之mappers

说明:

    mappers标签是用来引入映射文件的,项目中可以有多个映射文件(一张表对应一个实体类,对应一个mapper接口,对应一个映射文件),每个映射文件都要引入一次太麻烦,它也可以设置以包为单位来引入映射文件。要满足2个条件:(1)mapper接口所在的包要和映射文件所在的包一致,(2)mapper接口要和映射文件的名字一致。

注意:在resources目录下创建的不是包,而是目录结构。

注意:在resources下创建的多级目录是:com/atguigu/mybatis/mapper,中间以点的方式:com.atguigu.mybatis.mapper,相当于创建的是一个目录。只有在src/main/java目录下创建多级包才可以是点的方式:com.atguigu.mybatis.mapper。

把UserMapper.xml文件移动到创建的目录:com.atguigu.mybatis.mapper,并且要满足2个条件:(1)mapper接口所在的包要和映射文件所在的包一致。(2)mapper接口要和映射文件的名字一致。

 
    
        
        
        
    
五、设置核心配置文件/映射文件的模板

说明:每次以file的方式创建核心配置文件以及映射文件,文件的头信息都需要手动复制笔记或官网中的头信息 太过麻烦,可以设置模板,把文件头信息设置到模板中,此时在创建模板文件里面就有文件头信息了。

1、核心配置文件的模板

首先:编写好一个核心配置文件常用的标签,常用的一共4个:enviromnemts(设置数据库信息)、properties(引入properties文件)、typeAliases(设置类型别名)、mappers(设置以包的形式引入映射文件),要注意标签之间的顺序。





    

    
        
    

    
        
            
            
                
                
                
                
            
        
    

    
        
    

之后设置模板:


2、映射文件的模板

同样:先编写好一个映射文件的常用标签。



  


  
        select * from t_user
    

测试类:

//使用封装的工具类来测试:查询所有用户信息。
 @Test
    public void testGetAllUser(){
        //获取SqlSession对象是一个固定的过程,所以可以封装成工具类
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        List list = mapper.getAllUser();
        list.forEach(user -> System.out.println(user));
    }
七、MyBatis获取参数值的两种方式(重点)

说明:之前的映射文件的sql语句的参数是直接写死在sql语句中,正确的执行流程是:浏览器发送请求到服务器,控制层获取浏览器的请求参数,调用service传递到业务层,在调用mapper接口把请求参数传递到数据层,之后映射文件需要动态的获取mappper接口层的请求参数,并拼接到sql语句中。

MyBatis获取参数值的两种方式:

    ${} :本质就是字符串拼接,对应jdbc的字符串拼接Statement。
    使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号,会有sql注入问题#{}:本质就是占位符赋值,对应着jdbc的预编译占位符赋值PreparedStatement。
    使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号,没有sql注入问题。总结:尽量使用#{}占位符的方式赋值,但是有的sql必须使用${} 字符串拼接的方式。
1、单个字面量类型的参数

说明:若mapper接口中的方法参数为单个的字面量类型:

    此时可以使用${}和#{}以任意的名称获取参数的值,注意${}需要手动加单引号此时2种占位符里面的名字任意,但最好要做到见名之意。

测试:
mapper接口:

 
  User getUserByUsername(String username);

映射文件:


    
        
        select * from t_user where username = #{username} and password = #{password}
    

测试类:

    //3、若mapper接口方法的参数有多个时,可以手动将这些参数放在一个map中存储
    //   只需要通过#{}和${}以键的方式访问值即可,但是需要注意${}的单引号问题
    @Test
    public void testCheckLoginByMap(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        Map map = new HashMap<>();
        map.put("username", "admin");
        map.put("password", "123456");
        User user = mapper.checkLoginByMap(map);
        System.out.println(user);
    }
4、实体类类型的参数

若mapper接口中的方法参数为实体类对象时:

    此时可以使用${}和#{},通过访问实体类对象中的属性名获取属性值,注意${}需要手动加单引号底层调用的是set和get方法,要保证占位符里面的名字在实体类中有对应的set、get方法。注意:保证的是占位符里面的名字在实体类中有对应的set、get方法,而非和属性名保持一致,一般来说属性名就有对应的set、get方法,所以有时候也说占位符的名字和实体类的属性名保持一致。

测试:
实体类:

package com.atguigu.mybatis.pojo;


public class User {

    private Integer id;

    private String username;

    private String password;

    private Integer age;

    private String sex;

    private String email;

    public User() {
    }

    public User(Integer id, String username, String password, Integer age, String sex, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                ", age=" + age +
                ", sex='" + sex + ''' +
                ", email='" + email + ''' +
                '}';
    }
}

mapper接口:

 
    int insertUser(User user);

映射文件:


    
        insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
    

测试类:

 //4、mapper接口方法的参数是实体类类型的参数
    //   只需要通过#{}和${}以属性的方式访问属性值即可,但是需要注意${}的单引号问题
    @Test
    public void testInsertUser(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        int result = mapper.insertUser(new User(null, "李四", "123", 23, "男", "123@qq.com"));
        System.out.println(result);
    }
5、数组,list集合类型的参数

说明:mapper接口传递的是数组或者是list集合类型的参数,到动态SQL中讲解。

注意:这里指的是同一个参数,有多个值的情况。上面那是有多个不同类型的参数。

6、使用@Param标识参数

可以通过@Param注解标识mapper接口中的方法参数:

    此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储a>以@Param注解的值为键,以参数为值b>以param1,param2...为键,以参数为值因此只需要通过#{}和${}以键的方式访问值即可,但是需要注意${}的单引号问题总结使用场景:单个字面量类型的参数、多个字面量类型的参数。可以使用注解指定map集合中的key,在映射文件中通过key获取参数值,key有2种方式:以@Param注解的值为键,以param1,param2…为键。即:不想要系统指定的key,而是想要自己指定的key获取请求参数。建议:除了Map集合和实体类对象,其它的方式接收参数都加上@Param标识参数

mapper接口:

    User checkLoginByParam(@Param("username") String username, @Param("password") String password);

映射文件:

 
    
        select * from t_user where id = #{id}
    

测试类:

//1.1、若查询出的数据只有一条----->a>可以通过实体类对象接收
    @Test
    public void testGetUserById01(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        System.out.println(mapper.getUserById01(3));
    }
1.2、可以通过list集合接收

mapper接口:

     List getUserById02(@Param("id") Integer id);

映射文件:

 
    
    
        select * from t_user where id = #{id}
    

测试类:

//1.3、若查询出的数据只有一条----->c>可以通过map集合接收
    @Test
    public void testGetUserByIdToMap(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        //查询的结果:以字段为键,以字段值为值。{password=123456, sex=男, id=3, age=23, email=12345@qq.com, username=小明}
        System.out.println(mapper.getUserByIdToMap(3));
    }
2、查询出的数据有多条 2.1、可以通过实体类类型的list集合接收

mapper接口:

    List getAllUser();

映射文件:

    
        select * from t_user
    

测试类:

 //2.2若查询出的数据有多条------>b>可以通过map类型的list集合接收
    @Test
    public void testGetAllUserToMap(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        //[{password=123456, sex=男, id=1, age=23, email=12345@qq.com, username=admin},
        // {password=123456, sex=男, id=2, age=23, email=12345@qq.com, username=李四},
        // {password=123456, sex=男, id=3, age=23, email=12345@qq.com, username=小明}]
        System.out.println(mapper.getAllUserToMap());
    }
2.3、可以在mapper接口的方法上添加@MapKey注解

mapper接口:

@MapKey("id")//可以将每条数据转换的map集合作为值,以某个字段的值作为键,放在同一个map集合中
             //key要求是唯一的,所以只能是id值作为键
    Map getAllUserToMap02();

映射文件:

    
        select count(*) from t_user
    

测试类:

    //查询用户总记录数
    @Test
    public void testGetCount(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        System.out.println(mapper.getCount());
    }
九、特殊SQL的执行

说明:一些特殊的SQL在使用#{}占位符时,会有一些问题。

1、模糊查询

说明:使用#{}占位符来获取请求参数时,真正执行的sql语句中#{}占位符会被?来代替,现在使用的是模糊查询,所以#{}占位符是写在一对单引号中,而单引号在sql中表示的是一个字符串,也就是说此时#{}占位符会被解析为?并放在单引号中,即?放在字符串中,放在字符串中?不会当做占位符来解析,而是当做一个字符串参数来使用,所以当前我们的sql并没有占位符,而现在却为占位符赋了值,所以会报错。

解决:

    使用${}占位符使用sql里面的字符串函数concat,拼接#{}在%两边分别加上一对双引号进行拼接#{}(常用)

测试:
mapper接口:

 
    List getUserByLike(@Param("username") String username);

映射文件:


    
        select * from ${tableName}
    

测试类:

 @Test
    public void testGetUserByTableName(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        List list = mapper.getUserByTableName("t_user");
        System.out.println(list);
    }
4、添加功能获取自增的主键

t_clazz(clazz_id,clazz_name):班级表

t_student(student_id,student_name,clazz_id) :学生表

1、添加班级信息

2、获取新添加的班级的id

3、为班级分配学生,即将某学的班级id修改为新添加的班级的id

应用场景分析1:在一对多关系的班级表和学生表,表关系是设置在多的一方,即在学生表中设置对应班级的id。业务实现:此时向班级表添加一个信息,也应该向班级分配学生信息,那么添加完班级后如果要为学生设置,当前所在的班级就是刚才添加的班级时,那么这个当前班级的id是什么呢???只有获取到当前班级的id,才能为当前的班级分配学生。
应用场景分析2:多对多,关系数据放在中间表,此时添加了主表的信息,并且也为主表添加了从表的信息,那么此时应该把它们之间的关系添加在中间表中。这个时候就要知道刚才所添加数据的id是什么,在中间表一般添加的是这2张表的主键。

解决:

    jdbc本身提供了添加功能获取自增的主键。mybatis封装jdbc之后也可以获取添加功能获取自增的主键。

注意:前提是设置的主键自增。

测试:
mapper接口:

    void insertUser(User user);

映射文件:


    
        insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
    

测试类:

 //测试:mybatis获取添加功能获取自增的主键
    @Test
    public void testInsertUser(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        User user = new User(null, "王五", "123", 23, "男", "123@163.com");
        mapper.insertUser(user);
        //User的id添加时本身是null,执行完插入后发现id有值了,因为在mybatis实现添加操作时设置了要把当前自动递增的主键
        //放在所传输对象User的id属性中,不设置输出的id值为null
        System.out.println(user);
    }

    //jdbc获取添加功能获取自增的主键
    @Test
    public void testJDBC() throws Exception {
        Class.forName("");
        Connection connection = DriverManager.getConnection("", "", "");
        PreparedStatement ps = connection.prepareStatement("insert", Statement.RETURN_GENERATED_KEYS);
        ps.executeUpdate();
        ResultSet resultSet = ps.getGeneratedKeys();
    }
十、自定义映射resultMap 1、数据准备:

创建一对多关系的2张表:
部门表:t_dept

员工表t_emp:

在多的一方员工表设置部门表的主键,来保存一对多的表关系:

向2张表中添加数据:


设置对应的实体类:

package com.atguigu.mybatis.pojo;

import java.util.List;


public class Dept {

    private Integer did;

    private String deptName;

    private List emps;

    @Override
    public String toString() {
        return "Dept{" +
                "did=" + did +
                ", deptName='" + deptName + ''' +
                ", emps=" + emps +
                '}';
    }

    public List getEmps() {
        return emps;
    }

    public void setEmps(List emps) {
        this.emps = emps;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public Dept() {
    }

    public Dept(Integer did, String deptName) {
        this.did = did;
        this.deptName = deptName;
    }
}

package com.atguigu.mybatis.pojo;

import java.io.Serializable;


public class Emp {

    private Integer eid;

    private String empName;

    private Integer age;

    private String sex;

    private String email;


    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", empName='" + empName + ''' +
                ", age=" + age +
                ", sex='" + sex + ''' +
                ", email='" + email + ''' +
                ", dept=" + dept +
                '}';
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Emp() {
    }

    public Emp(Integer eid, String empName, Integer age, String sex, String email) {
        this.eid = eid;
        this.empName = empName;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }
}

2、实体类属性名和表的字段名不一致

说明:

    字段名和属性名不一致时,不会报错,而是如果字段有相对应的属性就可以赋上值,没有赋不上值。问题:能否通过修改字段名或者属性名,是它们2个的名字保持一致???
    表中字段名的命名规则:多个单词以下划线隔开。
    实体类中的属性命名规则:驼峰规则映射。
    所以:不能通过修改名字,使它们2个保持一致。思考:在不改变字段名或属性名的情况下,来如何解决映射关系呢???
    解决方式有3种:(1)为查询出来的字段设置别名。(2)、在核心配置文件中,开启驼峰映射。(3)通过resultMap设置自定义的映射关系。

数据库的字段:

实体类的属性:

结果导致赋不上值:

2.1、方式一:设置字段别名

说明:为查询出来的字段设置别名,保持和属性名的一致。
Mapper接口:

 
    List getAllEmp();

映射文件:


    
        select * from t_emp
    

测试类:

3、多对一映射处理

说明:既然表和表之间有映射关系,那么对应的实体类和实体类之间也要有映射关系。

比如:如何描员工所在的部门,以及部门所对应员工呢???

解决:对于多对一关系,首先需要在多的一方的实体类中,创建一的实体类对象,之后具体处理有三种方式。

查询员工信息以及员工所对应的部门信息

3.1 方式一:级联方式处理映射关系(不常用)

Mapper接口:

 
    Emp getEmpAndDept(@Param("eid") Integer eid);

映射文件:

 
    
        
        
        
        
        
        
        
        
    
    
    
        select * from t_emp left join t_dept on t_emp.did = t_dept .did where t_emp.eid = #{eid}
    

在次测试仍能访问成功。

3.3 方式三:分步查询(常用)

说明:用的还是方式二的association标签,只不过方式二是通过一条sql把数据查询出来然后在设置当前的映射,此时的方式三是通过分步把所需要的数据查询出来。

例如:查询员工信息就知道员工所对应的部门id,在通过部门的id查询部门所对应的信息,这样就可以把所需要的数据都查询查来,步骤:通过第一个sql查询出员工信息,通过第二个sql把查询出来的部门信息赋值给员工表对应的实体类中的dept属性。

1)查询员工信息

EmpMapper接口:

 
    Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);

EmpMapper.xml映射文件:

 
        
        
        
        
        
        
        
    

    
    
        select * from t_dept where did = #{did}
    

测试类:

 @Test
    public void testGetEmpAndDeptByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(3);
        System.out.println(emp);
    }
3.4 使用方式三:分步查询的好处

分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载

此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"

解释:

    延迟加载的好处是:在分步查询中可以设置延迟加载,如果只访问了员工的信息(第一步查询)那么只会执行一个sql,如果获取的是员工以及员工所在的部门信息 那么既会执行查询员工的sql又会执行查询部门的sql。lazyLoadingEnabled:延迟加载的全局开关,所有关联对象都会延迟加载。
    所有关联对象:即分步查询的第二步、第三步。
    说明:只要在核心配置文件中设置 lazyLoadingEnabled属性为开启(默认是false不开启),并且在映射文件中设置fetchType属性为关闭,那么就可以实现当前所有分步查询的操作都为懒加载。
    fetchType属性默认就是false关闭,所以可以不设置(mybatis<=3.4.1默认是true开启,之后的版本默认是false关闭)。aggressiveLazyLoading:可以在映射文件中设置具体的那些分步操作需要懒加载,那些需要立即加载。

核心配置文件:

 
 

测试1:当前设置的分布查询是既能查询员工信息又能查询员工对应的部门信息,因为设置的有延迟加载,所以如果只获取员工信息那么只会执行查询员工的sql,如果是查询的对应的部门信息那么此时2个sql都会执行。



测试2:如果没有在配置文件中配置延迟加载,那么即便此时只查询员工的信息,2个sql都会执行。


测试3:在核心配置文件中设置的 lazyLoadingEnabled属性是针对于当前所有的分步操作实现懒加载,但是有的分步功能不需要设置延迟加载 那么此时就可以在映射文件中添加fetchType属性实现延迟或立即加载。


        
        
        
        
        
        
        
    

4、一对多映射处理

说明:同样对于一对多关系的数据,首先要设置实体类之间的对应关系,在一的一方创建一个对象类型的集合属性,之后处理方式有2种。

4.1、方式一:使用collection处理映射关系

接口:

 
    Dept getDeptAndEmp(@Param("did") Integer did);

映射文件

 
        
        
        
        
            
            
            
            
            
            
        
    
    
    
        select * from t_dept where did = #{did}
    

2)根据部门id查询部门中的所有员工
同样开启驼峰规则映射,如果分步查询只有2步,一般分步查询操作的第二步就不需要在使用ResultMap标签了 比较麻烦,如果分布查询是涉及到更多的表的查询,比如5张表的一对多关系,那么此时第二步仍然需要使用ResultMap设置一对多的关系。

EmpMapper接口:

    
    List getDeptAndEmpByStepTwo(@Param("did") Integer did);

EmpMapper.xml映射文件:

 
    
        select * from t_emp
        
        
            
                emp_name =#{empName}
            
            
                and age = #{age}
            
            
                and sex = #{sex}
            
            
                and email = #{email}
            
        

    

此时只有第一个条件不满足,sql变为select * from t_emp where and age=12 and sex='男',where标签会自动去掉内容前面的and或者or变为:select * from t_emp where age=12 and sex='男',SQL执行成功。

测试2:and或or写在内容之后,即便where标签中的if条件满足,也不会去掉条件最后多余的and或or。

此时只有第一个条件满足,sql语句变为select * from t_emp where emp_name='小明' and,内容后面会多个and,where标签不会帮你自动去掉内容后的and或or,所以执行失败。

3、trim

说明:where标签不能去掉条件最后多余的and或or,此时使用trim标签代替where标签可以实现。

trim用于去掉或添加标签中的内容常用属性:

prefix:在trim标签中的内容的前面添加某些内容prefixOverrides:在trim标签中的内容的前面去掉某些内容suffix:在trim标签中的内容的后面添加某些内容suffixOverrides:在trim标签中的内容的后面去掉某些内容

测试:
修改映射文件:把where标签修改为trim标签,并设置属性。

 
    
        select * from t_emp
        
        
        
            emp_name =#{empName} and
        
        
             age = #{age} and
        
        
             sex = #{sex} and
        
        
             email = #{email}
        
        

    

即便and或or写在内容后面,此时只有第一个条件满足,仍然可以执行成功。

4、choose、when、otherwise

说明:

    choose、when、otherwise相当于java代码的if…else if…else之前是以if标签当做判断条件时,多个条件都会执行。使用此套标签用来判断时,只要有一个条件成立,其它的条件就不在判断了。choose:父标签when:子标签,相当于if…else if
    otherwise:子标签:相当于else

mapper接口

 
    List getEmpByChoose(Emp emp);

映射文件

 
    
        select * from t_emp where eid = #{eid}
    




测试类:

 @Test
    public void testOneCache(){
        SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
        Emp emp1 = mapper1.getEmpByEid(1);
        System.out.println(emp1);
        CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);
        Emp emp2 = mapper1.getEmpByEid(1);
        System.out.println(emp2);

    }
2、MyBatis的二级缓存

说明:二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置b>在映射文件中设置标签c>二级缓存必须在SqlSession关闭或提交之后有效d>查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

测试:
1)在映射文件中设置标签

2)查询的数据所转换的实体类类型必须实现序列化的接口

3)测试类:二级缓存必须在SqlSession关闭或提交之后有效

 @Test
    public void testTwoCache(){
        //不能再使用工具类了,因为每次调用都会创建一个新的sqlSessionFactory对象
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
            System.out.println(mapper1.getEmpByEid(1));
            sqlSession1.close();
            SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
            System.out.println(mapper2.getEmpByEid(1));
            sqlSession2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
3、二级缓存的相关配置

在mapper配置文件中添加的cache标签可以设置一些属性:

eviction属性:缓存回收策略
LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。默认的是 LRU。flushInterval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出readOnly属性:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。 4、MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。如果二级缓存没有命中,再查询一级缓存如果一级缓存也没有命中,则查询数据库SqlSession关闭之后,一级缓存中的数据会写入二级缓存 5、整合第三方缓存EHCache

说明:MyBatis是一个持久层框架,在缓存方面可能不是太专业,所以MyBatis提供了缓存的接口,可以由其它的第三方技术来代替二级缓存。

a>添加依赖

  
   
       org.mybatis.caches
       mybatis-ehcache
       1.2.1
   
   
   
       ch.qos.logback
       logback-classic
       1.2.3
   
b>各jar包功能
jar包名称作用
mybatis-ehcacheMybatis和EHCache的整合包
ehcacheEHCache核心包
slf4j-apiSLF4J日志门面包
logback-classic支持SLF4J门面接口的一个具体实现
c>创建EHCache的配置文件ehcache.xml

说明:名字必须为ehcache.xml。



    
    

    
    

d>设置二级缓存的类型


    
e>加入logback日志

说明:存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。

注意:名字也是固定的。

创建logback的配置文件logback.xml:



    
    
        
            
            
            [%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n
        
    

    
    
    
        
        
    

    
    


测试:最终实现的效果和MyBaris的二级缓存实现的效果相同,如缓存的级别:SqlSessionFactory,第二次查询相同的数据仍为缓存中的数据。

磁盘上的缓存文件:

f>EHCache配置文件说明

十三、MyBatis的逆向工程

说明:逆向工程本质上就是一个代码生成器。

正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程 的。逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

Java实体类Mapper接口Mapper映射文件 1、创建逆向工程的步骤 a>准备工作

1.创建一个Maven-java模块:

2.设置打包方式为jar包:

jar

3.添加其它的依赖:junit测试,log4j日志,MySQL驱动。

 
        
            junit
            junit
            4.12
            test
        

        
        
            mysql
            mysql-connector-java
            5.1.3
        

        
        
            log4j
            log4j
            1.2.17
        

4.添加其它配置文件:

a>添加依赖和插件

    
        
            org.mybatis
            mybatis
            3.5.7
        
    

    
    

        
        

            
            
                org.mybatis.generator
                mybatis-generator-maven-plugin
                1.3.0

                
                

                    
                    
                        org.mybatis.generator
                        mybatis-generator-core
                        1.3.2
                    

                    
                    
                        com.mchange
                        c3p0
                        0.9.2
                    

                    
                    
                        mysql
                        mysql-connector-java
                        5.1.8
                    
                
            
        
    
b>创建MyBatis的核心配置文件

说明:MyBatis的核心配置文件和逆向工程没有任何关系,但是如果没有核心配置文件就没有连接数据库的环境,也就不能写增删改查的代码,所以说如果要实现MyBatis逆向工程的crud操作时还是需要自己写核心配置文件的。





    

    
        
    


    
        
            
            
                
                
                
                
            
        
    

    
        
    

c>创建逆向工程的配置文件(清新简洁版)

文件名必须是:generatorConfig.xml




    
    
        
        
        
        
        
            
            
        
        
        
            
        
        
        
            
        
        
        
        
        
d>执行MBG插件的generate目标

效果:


查看mapper接口文件:
说明:这是清新简洁版,里面只有基本的5个方法,想要实现别的功能还要手动编写。以后我们主要用的是奢华尊享版。

查看映射文件:

2、QBC查询(奢华尊享版)

案例没有写测试:https://www.bilibili.com/video/BV1VP4y1c7j7?p=63&spm_id_from=pageDriver

首先:把之前的清新简洁版生成的文件删除掉。

其次:修改逆向工程的配置文件为奢华尊享版。

再次点击插件,生成文件:

pojo类明显变多了:

接口中的方法也明显增多了

十四、分页插件

说明:数据库的分页功能在MyBatis中,直接就可以使用分页插件来实现,不需要在sql语句中写分页的过程了。

1、分页插件使用步骤 a>添加依赖

  
   
       com.github.pagehelper
       pagehelper
       5.2.0
   
b>配置分页插件

在MyBatis的核心配置文件中配置插件,注意标签顺序。

	
       
       
   

2、分页插件的使用

a>在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能
pageNum:当前页的页码
pageSize:每页显示的条数b>在查询获取list集合之后,使用PageInfo pageInfo = new PageInfo<>(List list, int navigatePages)获取分页相关数据
list:分页之后的数据
navigatePages:导航分页的页码数c>分页相关数据(在查询功能之后获取更多的分页相关信息)
PageInfo{ pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8, list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30, pages=8, reasonable=false, pageSizeZero=false}, prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8, navigatepageNums=[4, 5, 6, 7, 8] }
常用数据:
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
isFirstPage/isLastPage:是否为第一页/最后一页
hasPreviousPage/hasNextPage:是否存在上一页/下一页
navigatePages:导航分页的页码数
navigatepageNums:导航分页的页码,[1,2,3,4,5]

测试:
mapper接口:

 List getAllEmpTest();

映射文件:

 
    
        select * from t_emp
    

测试类1:

package com.atguigu.mybatis.test;

import com.atguigu.mybatis.mapper.EmpMapper;
import com.atguigu.mybatis.pojo.Emp;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class PageHelperTest {

    

    @Test
    public void testPageHelper(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            //  需要在查询功能之前开启分页功能:
            //      参数: 当前页的页码,每页显示的条数
            //这个方法有返回值为Page对象,里面保存的是分页之后的相关数据
            Page page = PageHelper.startPage(1, 4);
            List list = mapper.getAllEmpTest();
            list.forEach(emp -> System.out.println(emp));
            System.out.println(page);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

 


分页相关数据:

Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=12, pages=3, reasonable=false, pageSizeZero=false}
[Emp{eid=1, empName='小明', age=12, sex='男', email='123@.com', dept=null},
 Emp{eid=2, empName='小黑', age=11, sex='男', email='123@.com', dept=null}, 
 Emp{eid=3, empName='小花', age=13, sex='女', email='123@.com', dept=null}, 
 Emp{eid=4, empName='小兰', age=15, sex='女', email='123@.com', dept=null}]

测试类2:说明,分页相关的数据大部分都保存在当前的Page对象中,那么我们可以直接通过page对象里面的相关分页数据。如果想要获取的数据更多的话,可以通过PageInfo在查询功能之后获取分页相关信息。

package com.atguigu.mybatis.test;

import com.atguigu.mybatis.mapper.EmpMapper;
import com.atguigu.mybatis.pojo.Emp;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class PageHelperTest {

    
    @Test
    public void testPageHelper(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            //  需要在查询功能之前开启分页功能:
            //     参数:  当前页的页码,每页显示的条数
            //这个方法有返回值,可以获取分页之后的相关数据
            //Page page = PageHelper.startPage(1, 4);
             PageHelper.startPage(2, 4);//修改为,不使用page对象来接收。
            List list = mapper.getAllEmpTest();
            //在查询功能之后获取分页相关信息(这种方式可以获取更多的分析信息)
            //参数:分页之后的数据,表示当前导航分页的数量
            //导航分页的数量:一个页面中显示:首页 尾页 _ _ _ _ _  上一页 下一页
            //           中间是一个个的页码值,比如当前访问的是第5页显示为:首页 尾页  3 4 5 6 7 上一页 下一页
            //                              从当前页数-2开始,从当前页数+2结束
            //           特殊情况:假如一共有10页:
            //                   如果访问的页数是第一页,第二页,那么不能在-2,因为前面没有页数了,显示的页数是固定的
            //                                            只能显示为:首页 尾页  1 2 3 4 5 上一页 下一页。
            //                   如果访问的页数是最后2页,那么不能在+2,因为后面没有页数了,显示的页数是固定的
            //                                            只能显示为:首页 尾页  6 7 8 9 10 上一页 下一页。
            //总结:导航分页的数量指的就是:当前页面展示几个导航分页,一般是奇数。如果是偶数:左边展示2个右边展示3个显示不合适。
            PageInfo page = new PageInfo<>(list, 5);
            list.forEach(emp -> System.out.println(emp));
            System.out.println(page);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

 

分页相关数据:明显比第一种获取的分页相关数据更多。

PageInfo{

pageNum=2, pageSize=4, size=4, startRow=5, endRow=8, total=12, pages=3, 

list=Page{count=true, pageNum=2, pageSize=4, startRow=4, endRow=8, total=12, pages=3,
reasonable=false, pageSizeZero=false}
[Emp{eid=5, empName='小白', age=12, sex='女', email='123@.com', dept=null}, 
Emp{eid=18, empName='a',age=null, sex='null', email='null', dept=null},
Emp{eid=19, empName='a', age=null, sex='null', email='null', dept=null}, 
Emp{eid=20, empName='a',age=null, sex='null', email='null', dept=null}], 

prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, 
navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]
}

多的部分:

PageInfo{

pageNum=2, pageSize=4, size=4, startRow=5, endRow=8, total=12, pages=3, 



prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, 
navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号