Java Mybatis狂神说的详细笔记(完整版)


Mybatis官方文档:

Mybatis官方文档

官网文档: https://mybatis.org/mybatis-3/zh/getting-started.html

MyBatis

1、简介

1.1 什么是Mybatis

在这里插入图片描述

  • MyBatis 是一款优秀的持久层框架;
  • 它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1.2 持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(Jdbc),io文件持久化。

为什么要持久化?

有一些对象,不能让他丢掉
内存太贵

1.3 持久层

Dao层、Service层、Controller层

  • 完成持久化工作的代码块
  • 层界限十分明显

1.4 为什么需要MyBatis

  • 帮助程序员将数据存入到数据库中

  • 方便

  • 传统的JDBC代码太复杂了,简化,框架,自动化

  • 不用MyBatis也可以,技术没有高低之分

  • 优点:

    • 简单易学
    • 灵活
    • sql和代码的分离,提高了可维护性。
    • 提供映射标签,支持对象与数据库的orm字段关系映射
    • 提供对象关系映射标签,支持对象关系组建维护
    • 提供xml标签,支持编写动态sql

2、第一个Mybatis程序

思路:搭建环境 --> 导入MyBatis --> 编写代码 --> 测试

2.1 搭建环境

创建数据库

CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `name` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称',
    `pwd` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,"狂神","123456"),
(2,"通达","123456"),
(3,"蓝凌","123456");

新建项目 

1.创建一个普通的maven项目

2.删除src目录 (就可以把此工程当做父工程了,然后创建子工程)

3.导入maven依赖



    
    
        mysql
        mysql-connector-java
        8.0.12
    
    
    
        org.mybatis
        mybatis
        3.5.4
    
    
    
        junit
        junit
        4.12
        test
    


4.创建一个Module

2.2 创建一个模块

  • 编写mybatis的核心配置文件
    <?xml version="1.0" encoding="UTF-8" ?>
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    
        default="development">
            
                
                
                    
                    
                    
                    
                
            
        
    

    详解:
    <?xml version="1.0" encoding="UTF-8" ?>
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">























  此处设useSSL=false。

  • 编写mybatis工具类  
//SqlSessionFactory -->SqlSession
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;
    static {

        try {
            //使用Mybaties第一步:获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
    public static SqlSession getSqlSession(){
//        SqlSession sqlSession =  sqlSessionFactory.openSession();
//        return sqlSession;

        return sqlSessionFactory.openSession();
    }

}

2.3 编写代码

  • 实体类
    //实体类
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
  • Dao接口
public interface UserDao {
    List getUserList();
}
  • 接口实现类由原来的UserDaoImpl转变成一个Mapper配置文件。
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">









junit测试.

注意点:会报错

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什么?

核心配置文件中注册mappers

    @Test
    public void test(){

        //1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行SQL
        // 方式一:getMapper
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List userList = userDao.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }

        //关闭sqlSession
        sqlSession.close();
    }

mybatis-config.xml中


    
        
    

可能会遇到的问题:

  • 配置文件没有注册
  • 绑定接口错误
  • 方法名不对
  • 返回类型不对
  • Maven导出资源问题

3、CURD
 1. namespace
namespace中的包名要和Dao/Mapper接口的包名一致

<?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">





    
    
    
    

 2. select

选择,查询语句;

id:就是对应的namespace中的方法名;

resultType : Sql语句执行的返回值;

parameterType : 参数类型;

  1.编写接口:UserMapper.java

public interface UserMapper {
    //查询所有用户
    public List getUserList();
    //插入用户
    public void addUser(User user);
}

  2.编写对应的mapper中的sql语句:UserMapper.xml


    insert into user (id,name,password) values (#{id}, #{name}, #{password})

  3.测试:UserMapperTest.java

@Test
public void test2() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user  = new User(3,"黑子","666");
    mapper.addUser(user);
    //增删改一定要提交事务
    sqlSession.commit();

    //关闭sqlSession
    sqlSession.close();
}

注意:增删改查一定要提交事务:

sqlSession.commit();

增删改查全部流程实现

3. Insert

4. update

5. Delete

UserMapper.java

//Dao以后等价mapper
public interface UserMapper {
    //返回所有用户
    List getUserList();

    //根据Id查询用户,User为返回值用户
    User getUserById(int id);

    //insert一个用户,参数是对象User
    int addUser(User user);

    //修改用户
    int updateUser(User user);

    //删除一个用户
    int deleteUser(int id);

}

UserMapper.xml

<?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">





    
    
    
    

    
    

    
    
        insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});
    

    
    
        update mybatis.user set name=#{name},pwd=#{pwd} where id =#{id};
    

    
        delete from mybatis.user where id =#{id};
    

UserDaoTest.java

package com.tongda.dao;

import com.tongda.pojo.User;
import com.tongda.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

/**
 * @Author JunLong
 * @Date 2022/4/5 6:59
 * @Version 1.0
 */
/*注意点:

        org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

        MapperRegistry是什么?

        核心配置文件中注册mappers
        */
public class UserDaoTest {
    @Test
    public void test(){
        //第一步:获取SqlSession对象,工具类MybatisUtils中
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行Sql:方式一getMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List userList = mapper.getUserList();

        // 方法一:
        for (User user : userList) {
            System.out.println(user);
        }

        //不推荐:方法二
        // List userList = sqlSession.selectList("com.tongda.UserDao.getUserList");
        // for (Object user : userList) {
        //     System.out.println(user);
        //
        // }

        //关闭sqlSession
        sqlSession.close();
    }

    @Test
    public  void getUserById(){
        //第一步固定步骤写法
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //获得UserMapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //getUserbyid(用户id号)
        User user1 = mapper.getUserById(1);
        User user2 = mapper.getUserById(2);
        User user3 = mapper.getUserById(2);
        System.out.println(user1);
        System.out.println(user2);
        System.out.println(user3);

        sqlSession.close();
    }

    //增删改必须提交事务
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

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

        int res = mapper.addUser(new User(4, "哼哈", "123456"));
        if (res>0){
            System.out.println("插入成功!");
        }

        // 提交事务,增删改必须提交事务
        sqlSession.commit();
        //关闭
        sqlSession.close();;
    }

    @Test
    public void updataUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(4,"呵呵","123123"));

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

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(4);

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

6.分析错误

  1.标签不要匹配错 com.tongda.dao.UserMapper;

  2.resource绑定mapper,需要使用路径! com/tongda/dao/UserMapper  注意分隔符;

  3.程序配置文件必须符合规范;

  4.NullPointerException,没有注册到资源Utils中sqlSessionFactory作用域问题;

  5.乱码问题,或者idea-setting-file encoding-utf-8

  6.maven资源没有导出问题,pom.xml中在build中配置resources,来防止我们资源导出失败的问题

7.万能的Map

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该考虑使用Map!

UserMapper接口
//用万能Map插入用户

public void addUser2(Map map);

UserMapper.xml



insert into user (id,name,password) values (#{userid},#{username},#{userpassword})

测试UserDaoTest

@Test
public void test3(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap map = new HashMap();
    map.put("userid",4);
    map.put("username","王虎");
    map.put("userpassword",789);
    mapper.addUser2(map);
    //提交事务
    sqlSession.commit();
    //关闭资源
    sqlSession.close();
}

Map传递参数,直接在sql中取出key即可! 【parameter=“map”】

对象传递参数,直接在sql中取出对象的属性即可! 【parameter=“Object”】

只有一个基本类型参数的情况下,可以直接在sql中取到

多个参数用Map , 或者注解!

7.模糊查询

模糊查询怎么写?

Java代码执行的时候,传递通配符% %

    

经常碰到这样的面试题目:#{}和${}的区别是什么?
 
网上的答案是:#{}是预编译处理,$ {}是字符串替换。

mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

mybatis在处理 时,就是把">时,就是把时,就是把{ } 替换成变量的值。

使用 #{} 可以有效的防止SQL注入,提高系统安全性。

sql注入指的是用户输入 or 1=1等变量导致原sql语句逻辑发生了变化,使得可以直接进入数据库,而使用预编译的方法可以让sql语句只把传入的数据当做参数进行处理

而不会改变原有sql的逻辑,preparestatement和#{}都是把变量预编译,防止sql注入。

4、配置解析

1. 核心配置文件

  • mybatis-config.xml

  • Mybatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息。 

configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
        environment(环境变量)
            transactionManager(事务管理器)
            dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)

2. 环境配置 environments
MyBatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

学会使用配置多套运行环境!

注意一些关键点:

  • 默认使用的环境 ID(比如:default="development")。
  • 每个 environment 元素定义的环境 ID(比如:id="development")。
  • 事务管理器的配置(比如:type="JDBC")。
  • 数据源的配置(比如:type="POOLED")。

默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

MyBatis默认的事务管理器就是JDBC ,连接池:POOLED

3. 属性 properties
我们可以通过properties属性来实现引用配置文件

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.poperties】

  1.编写一个配置文件

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=root
password=123456

2.在核心配置文件中引入



    
    
<?xml version="1.0" encoding="UTF-8" ?>
DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">


    
    
    

    
    default="development">
        
        
            
            
            

                
                
                
                
                
                
                
                
                
            
        
    
    
    
        
    

1.可以直接引入外部文件

2.可以在其中增加一些属性配置

3.如果两个文件有同一个字段,优先使用外部配置文件的

注意点:核心配置文件书写标签配置顺序

properties放在最前面

4. 类型别名 typeAliases

  • 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置.

  • 意在降低冗余的全限定类名书写。