Mybatis框架技术总结

Posted 生命是有光的

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis框架技术总结相关的知识,希望对你有一定的参考价值。

0、目录总览

1、分页插件

1.1、分页插件介绍

  • 分页可以将很多条结果进行分页显示。
  • 如果当前在第一页,则没有上一页。如果当前在最后一页,则没有下一页。
  • 需要明确当前是第几页,这一页中显示多少条结果。
  • MyBatis分页插件总结
    1. 在企业级开发中,分页也是一种常见的技术。而目前使用的 MyBatis 是不带分页功能的,如果想实现分页的 功能,需要我们手动编写 LIMIT 语句。但是不同的数据库实现分页的 SQL 语句也是不同的,所以手写分页 成本较高。这个时候就可以借助分页插件来帮助我们实现分页功能。
    2. PageHelper:第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单。

1.2、SQL语句分页

  • limit
  • 参数
    • 当前页( *(当前页-1)每页显示的条数
    • 每页显示的条数
-- 第一页,每页显示三条
select * from student limit 0,3;
-- 第二页,每页显示三条
select * from student limit 3,3;
-- 第三页,每页显示三条
select * from student limit 6,3;

1.3、分页插件的使用

MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据

开发步骤:

  1. 导入与PageHelper相关的jar包
<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>3.1</version>
</dependency>



<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>
  1. 在mybatis核心配置文件中配置PageHelper插件
<!--集成分页助手插件-->
<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor"
</plugins>
  1. 测试分页数据获取
public void selectPaging() throws Exception{
    //1.加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
    //2.获取SqlSession工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    //3.通过工厂对象获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession("true");
    //4.获取StudentMapper接口的实现类对象
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    //5.调用实现类的方法,接受结果
    List<Student> list = mapper.selectAll();
    //通过分页助手来实现分页功能
    //第一页:显示3条数据
    PageHelper.startPage(1,3);
    //第二页:显示3条数据
    PageHelper.startPage(2,3);
    //第二页:显示3条数据
    PageHelper.startPage(3,3);
    //6.处理结果
    for(Student student:list){
        System.out.println(student);
    }
}

1.4、分页插件的参数获取

public void selectPaging() throws Exception{
    //1.加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
    //2.获取SqlSession工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    //3.通过工厂对象获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession("true");
    //4.获取StudentMapper接口的实现类对象
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    //5.调用实现类的方法,接受结果
    List<Student> list = mapper.selectAll();
    //其他分页的数据
    PageInfo<Student> pageInfo = new PageInfo<>(list);
    System.out.println("总条数:"+pageInfo.getTotal());
    System.out.println("总页数:"+pageInfo.getPages());
    System.out.println("当前页:"+pageInfo.getPageNum());
    System.out.println("每页显示条数:"+pageInfo.getPageSize());
    System.out.println("上一页:"+pageInfo.getPrePage());
    System.out.println("下一页:"+pageInfo.getNextPage());
    System.out.println("是否第一页:"+pageInfo.isIsFirstPage());
    System.out.println("是否最后一页:"+pageInfo.isIsLastPage());
    
    
    //6.处理结果
    for(Student student:list){
        System.out.println(student);
    }
}

1.5、分页插件小结

分页:可以将很多条结果进行分页显示。

  • 分页插件 jar 包: pagehelper-5.1.10.jar jsqlparser-3.1.jar

  • <plugins>:集成插件标签。

  • 分页助手相关 API

    ​ 1.PageHelper:分页助手功能类。

    1. startPage():设置分页参数
    2. PageInfo:分页相关参数功能类。
    3. getTotal():获取总条数
    4. getPages():获取总页数
    5. getPageNum():获取当前页
    6. getPageSize():获取每页显示条数
    7. getPrePage():获取上一页
    8. getNextPage():获取下一页
    9. isIsFirstPage():获取是否是第一页
    10. isIsLastPage():获取是否是最后一页

2、Mybatis多表操作

2.1、多表模型介绍

我们之前学习的都是基于单表操作的,而实际开发中,随着业务难度的加深,肯定需要多表操作的。

  • 多表模型分类
    • 一对一:在任意一方建立外键,关联对方的主键。
    • 一对多:在多的一方建立外键,关联一的一方的主键。
    • 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键。

2.2、多表模型一对一操作

  1. 一对一模型: 人和身份证,一个人只有一个身份证

  2. 代码实现

    • 步骤一: sql语句准备

      CREATE TABLE person(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	NAME VARCHAR(20),
      	age INT
      );
      INSERT INTO person VALUES (NULL,'张三',23);
      INSERT INTO person VALUES (NULL,'李四',24);
      INSERT INTO person VALUES (NULL,'王五',25);
      
      
      CREATE TABLE card(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	number VARCHAR(30),
      	pid INT,
          -- 银行卡表的pid指向person表中的主键id
      	CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id)
      );
      INSERT INTO card VALUES (NULL,'12345',1);
      INSERT INTO card VALUES (NULL,'23456',2);
      INSERT INTO card VALUES (NULL,'34567',3);
      
    • 步骤二:实体类和接口

      public class Person{
          private Integer id;		//主键id
          private String name;	//人的姓名
          private Integer age;	//人的年龄
          //省略get/set,有参/无参方法
          
      }
      
      public class Card{
          private Integer id;		//主键id
          private String number;	//身份证号
          private Person 	p;		//所属人的对象
          //省略get/set,有参/无参方法
      }
      
      public interface OneToOneMapper{
          //查询全部
          public abstract List<Card> selectAll();
      }
      
    • 步骤三:配置文件

      <?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.itheima.table01.OneToOneMapper">
          <!--配置表中字段和实体对象属性的映射关系-->
          <resultMap id="oneToOne" type="card">
              <id column="cid" property="id" />
              <result column="number" property="number" />
              <!--
                  association:配置被包含对象的映射关系
                  property:被包含对象的变量名
                  javaType:被包含对象的数据类型
              -->
              <association property="p" javaType="person">
                  <id column="pid" property="id" />
                  <result column="name" property="name" />
                  <result column="age" property="age" />
              </association>
          </resultMap>
      
          <select id="selectAll" resultMap="oneToOne">
              SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
          </select>
      </mapper>
      
    • 步骤四:在MyBatisConfig.xml中引入配置文件

      <!--mappers引入映射配置文件-->
      <mappers>
          <mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"></mapper>
      </mappers>
      
    • 步骤五:测试类

      @Test
      public void selectAll() throws Exception{
          //1.加载核心配置文件
          InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
      
          //2.获取SqlSession工厂对象
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
      
          //3.通过工厂对象获取SqlSession对象
          SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
          //4.获取OneToOneMapper接口的实现类对象
          OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class);
      
          //5.调用实现类的方法,接收结果
          List<Card> list = mapper.selectAll();
      
          //6.处理结果
          for (Card c : list) {
              System.out.println(c);
          }
      
          //7.释放资源
          sqlSession.close();
          is.close();
      }
      

2.2.1、ResultMap

  • 当涉及多表操作时,用resultMap

  • 当只是单表操作时,用resultType

  1. resultMap:用来自定义结果集和实体类的映射
  • id属性:相当于这个resultMap的唯一标识
  • type 属性:用来指定映射到哪个实体类
  1. id 标签:用来指定主键列的映射规则
  • column 属性::数据库表的列名

  • property 属性:: 对应实体类的属性名

  1. result 标签:用来指定普通列的映射规则
  • column 属性::数据库表的列名
  • property属性: : 对应实体类的属性名
  1. association标签:配置被包含对象的映射规则
  • property属性:被包含对象的变量名
  • javaType属性:被包含对象的数据类型
  1. collection标签:配置被包含集合对象的映射规则。
  • property属性:被包含集合对象的变量名
  • ofType属性:集合中保存的对象数据类型

结果集映射ResultMap

要解决的问题:属性名和字段名不一致

2.2.2、查询为null问题

  1. 例如数据库字段名

  1. Java中实体类设计
public class User {
	private int id; //id
	private String name; //姓名
	private String password; //密码和数据库不一样!
	//构造
	//set/get
	//toString()
}
  1. UserMapper接口
public interface UserMapper {
    //根据id查询用户
    User selectUserById(int id);
}
  1. mapper 映射文件
<select id="selectUserById" resultType="com.kuang.pojo.User">
	select * from user where id = #{id}
</select>
  1. 测试
@Test
public void testSelectUserById() {
    SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.selectUserById(1);
    System.out.println(user);
    session.close();
}

结果

  • User{id=1,name='狂神',password='null'}
  • password 字段为空,因为实体类和数据库字段不一致,一个是pwd,一个是password

分析

  • select * from mybatis.user where id = #{id} 可以看作
  • select id,name,pwd from mybatisuser where id = #{}
  • mybatis 会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写),去对应的实体类中查找相应列名的 set 方法设值,由于找不到 setPwd() ,所以password返回null

2.2.3、解决方案

方案一:为列名指定别名,别名和 java 实体类的属性名一致

<select id="selectUserById" resultType="com.kuang.pojo.User">
	select id , name , pwd as password from mybatis.user where id = #{id}
</select>

方案二:使用结果集映射 ➡ ResultMap (推荐)

<resultMap id="UserMap" type="User">
	<!-- id为主键 -->
	<id column="id" property="id"/>
	<!-- column是数据库表的列名 , property是对应实体类的属性名 -->
	<result column="name" property="name"/>
	<result column="pwd" property="password"/>
</resultMap>

<!--使用我们自定义的映射规则-->
<select id="selectUserById" resultMap="UserMap">
	select id , name , pwd from mybatis.user where id = #{id}
</select>

2.3、多表模型一对多操作

  1. 一对多模型: 一对多模型:班级和学生,一个班级可以有多个学生。

  2. sql语句准备

-- 班级表
CREATE TABLE classes(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);
INSERT INTO classes VALUES (NULL,'黑马一班');
INSERT INTO classes VALUES (NULL,'黑马二班');

-- 学生表的cid指向班级表的主键id
CREATE TABLE student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30),
	age INT,
	cid INT,
	CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id)
);
INSERT INTO student VALUES (NULL,'张三',23,1);
INSERT INTO student VALUES (NULL,'李四',24,1);
INSERT INTO student VALUES (NULL,'王五',25,2);
INSERT INTO student VALUES (NULL,'赵六',26,2);

  1. 实体类和接口
public class Student {
    private Integer id;	//主键id
    private String name;//学生姓名
    private Integer agel//学生年龄
     //省略get/set,有参/无参方法
}
public class Classes {
    private Integer id;	//主键id
    private String name;//班级名称
    private List<Student> students;	//班级中所有学生对象
}
public interface OneToManyMapper {
    //查询全部
    public abstract List<Classes> selectAll();
}
  1. 配置文件
<mapper namespace="com.itheima.table02.OneToManyMapper">
    <resultMap id="oneToMany" type="classes">
        <id column="cid" property="id"/>
        <result column="cname" property="name"/>

        <!--
            collection:配置被包含的集合对象映射关系
            property:被包含对象的变量名
            ofType:被包含对象的实际数据类型
        -->
        <collection property="students" ofType="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="sage" property="age"/>
        </collection>
    </resultMap>
    
    <select id="selectAll" resultMap="oneToManyMybatis框架技术总结

MyBatis框架—动态 SQL配置文件事务

Spring+SpringMVC+MyBatis+Maven框架整合

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

黑马程序员-MyBatis 框架-最全入门笔记阿伟看了都得说真大真细真全!!!

Mybatis总结: