【开发】后端框架——Mybatis

前置知识:JDBC

学习视频

Mybatis——一种ORM框架:将Java中的Bean映射为数据库的记录

  • ORM:用于实现面向对象编程语言里不同类型系统的数据之间的转换

Mybatis运行过程——工厂模式

#{}${} ——三点区别

动态Sql

分页——两种方法

缓存——查询缓存顺序

MyBatis

文档

官方文档

下载链接

sql相关

  • sql引擎
  • innoDB底层
  • 索引
  • 索引优化

概述

JDBC

JDBC驱动程序:JDBC(Java Database Connectivity, Java 数 据 库 连 接)是 一 种可用于执行 SQL 语句的 Java API(Application Programming Interface)

  • 实现了从 Java 程序内调用标准的 SQL命令 对数据库进行查询、插入、删除和更新等操作, 并确保数据事务的正常进行

  • 基本层次结构由 Java 程序、JDBC 驱动程序管理器、数据库驱动程序和数据库四部分组成

    在这里插入图片描述

  • Java 程序依赖于 JDBC API,通过 DriverManager 来获取驱动,并且针对不同的数据库可以使用不同的驱动。

  • 这是典型的桥接的设计模式,把 抽象 Abstraction行为实现Implementation 分离 开来,从而可以保持各部分的独立性以及应对他们的功能扩展。

JDBC步骤

在这里插入图片描述

public static void connectionTest(){
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
 
    try {
        // 1. 加载并注册 MySQL 驱动器实例
        Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
        // 2. 将Mysql驱动程序注册到驱动管理程序中
		//        根据特定的数据库连接URL,返回与此URL所匹配的数据库驱动对象
        Driver driver = DriverManager.getDriver("jdbc:mysql://localhost:3306/[dbName]"); 
        // 3. 传入参数,比如说用户名和密码
        Properties props = new Properties();
        props.put("user", USER_NAME);
        props.put("password", PASSWORD);
        
        // 4. 使用数据库驱动创建数据库连接 Connection
        connection = driver.connect(URL, props);
 
        // 5. 从数据库连接 connection 中获得 Statement 对象
        statement = connection.createStatement();
        // 6. 执行 sql 语句,返回结果
        resultSet = statement.executeQuery("select * from activity");
        // 7. 处理结果,取出数据
        while(resultSet.next()){
            System.out.println(resultSet.getString(2));
        }
        .....
    }finally{
        // 8.关闭链接,释放资源  按照JDBC的规范,使用完成后管理链接,
        // 释放资源,释放顺序应该是: ResultSet ->Statement ->Connection
        resultSet.close();
        statement.close();
        connection.close();
    }
}

在这里插入图片描述

JDBC存在的问题
  • 传统的JDBC代码复杂
  • 实现步骤多
  • 需要设计一种 将数据映射到数据库的框架 来简化JDBC的步骤

Mybatis特点

  • 持久层框架

    持久化:将程序中的数据从 瞬时状态【内存:断电即失】转化为 持久状态【数据库jdbc,io文件持久化】的过程

    持久层:完成数据持久化工作的代码块,层次间界限分明

  • 定制化Sql

  • 避免JDBC代码,手动设置参数和获取结果集

优点

  • 简单:两个jar文件(mybatis.jar+mysql-connector.jar)+配置几个sql映射文件(Mapper)
  • 灵活:sql写在xml里,统一管理(mybatis-config.xml
  • 解除sql与程序的耦合:通过提供Mapper层,将业务逻辑与数据访问逻辑分离
  • 提供映射标签:JavaBean与数据库字段的关系映射
  • 提供xml标签,支持编写动态sql

Mybatis执行流程

通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO

  1. 获取配置文件
  2. 实例化 SqlSessionFactoryBuilder
  3. 加载 mybatis-config.xml 中的配置信息
  4. 实例化 SqlsessionFactory
  5. 创建执行器 executor
  6. 创建 SqlSession
  7. 实现CRUD逻辑
  8. CRUD后提交事务,判断是否执行成功
Resources获取加载全局配置文件
实例化SqlSessionFactoryBuilder构造器
解析配置文件流XMLConfigBuilder
Configuration加载所有的配置信息
SqlSessionFactory实例化
transactional事务管理器
创建executor执行器
创建SqlSession
实现CRUD
查看是否执行成功
提交事务
关闭
1. 导包——Maven
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.6</version>
</dependency>
SqlSessionFactoryBuilder

一旦创建了 SqlSessionFactory ,就不再需要它了。

因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域

  • 作用域:局部变量
SqlSessionFactory <=> 数据库连接工厂

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心

构造方法:从xml中配置文件中构建SqlSessionFactory实例

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在

  • 作用域:应用作用域

最简单的就是使用单例模式或者静态单例模式。

SqlSession => JDBC:Connection对象

通过 SqlSessionFactory 获得 SqlSession 的实例。

SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。

SqlSession的实例时线程不安全的,不能被共享

  • 每次收到一个数据库访问请求,打开一个SqlSession,返回响应后,立即关闭
Mapper => JDBC:Statement

代理对象 执行具体业务

将接口与xml进行绑定

在这里插入图片描述

Mybatis示例程序

搭建环境
编写代码
测试
导入mysql驱动,MyBatis包
核心配置文件mybatis-config.xml
编写工具类提供SqlSession对象

1. 搭建数据库

create table user(
	id int(11) not null primary key,
    user_name varchar(30) default null,
    pwd varchar(30) default null
)engine=InnoDB default charset=utf8;

insert into user(id,user_name,pwd) values
(1,'a','123456'),
(2,'b','123456'),
(3,'c','c123456');

2. 新建项目

在这里插入图片描述

3. 删除src,使项目成为父工程

4. maven导入依赖

<!-- 父工程 -->
<groupId>com.kuang.MyBatis</groupId>
<artifactId>MyBatis</artifactId>
<version>1.0-SNAPSHOT</version>

<!-- 导入依赖 -->
<dependencies>
    <!-- 导入MySql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>

    <!-- 导入MyBatis驱动 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>

    <!-- 导入junit依赖 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

5. 新建模块

在这里插入图片描述

6. 获取数据库连接对象

a. 编写核心配置文件——mybatis-config.xml

在这里插入图片描述

<?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">
<!-- configuration的核心配置 -->
<configuration>
    <!-- 可配置多套环境,defaulte属性选择当前属性 -->
    <environments default="development">
        <environment id="development">
            <!-- 事务管理器 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- 配置数据库驱动器类型及连接参数 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="2017002231"/>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 每一个Mapper.xml都需要在MyBatis核心配置文件中注册 -->
    <mappers>
        <mapper resource="com/kuang/dao/UserMapper.xml"/>
    </mappers>
</configuration>
  • useSSL:使用安全连接
  • useUnicode:保证中文不乱码
  • characterEncoding:编码格式

在这里插入图片描述

b. 编写MyBatis工具类

新建dao包,utils包

在这里插入图片描述

public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    
    // 1.获取SqlSessionFactory对象
    static{
        try {
            //1. 将资源中的配置文件以流的形式读入
            String resource = "mybatis-config.xml";
            InputStream configuration = Resources.getResourceAsStream(resource);

            //2. 通过工厂类构建器构建SqlSessionFactory类
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 2.获取SqlSession对象
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

在这里插入图片描述

7. 编写代码

在这里插入图片描述

实体类

pojo的作用就是将从数据库获取到的数据封装为一个一个的对象,让java能够更好的进行操作DO、VO

package com.kuang.pojo;

public class User {
    private Integer id;
    private String user_name;
    private String pwd;

    public User(){}

    public User(Integer id, String user_name, String pwd) {
        this.id = id;
        this.user_name = user_name;
        this.pwd = pwd;
    }

    public Integer getId() {
        return id;
    }


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

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", user_name='" + user_name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
Dao接口
public interface UserDao{
    List<User> getUserList();
}
接口的实现

由 UserDaoImpl 转化为 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">

<!-- 绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="com.kuang.dao.UserDao">
    <!--id:方法名-->
    <select id="getUserList" resultType="com.kuang.pojo.User">
        select *from mybatis.user;
    </select>
</mapper>
  • namespace:相当于指定要实现的接口
    • 将不同的语句隔离开来,同时也实现了接口绑定
      • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用
      • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
  • id:方法名
  • resultType:返回单个
  • resultMap:返回多个

8. 测试

新建 测试类

在这里插入图片描述

编写测试代码

package com.kuang.dao;

import com.kuang.pojo.User;
import com.kuang.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {
    @Test
    public void test(){
        //1.获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        //2.执行Sql
//通过反射机制,获取方法区中UserMapper的Class类实例,这个实例中有UserMapper全部信息
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();

        /*
        //方式二:强制类型转换,不安全
        List<User> userList = sqlSession.selectOne("com.kuang.UserDao.getUserList");
        */

        for (User user:userList){
            System.out.println(user);
        }

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

遇到的各种错误

org.apache.ibatis.io不存在——IDEA2020.1

在这里插入图片描述

在这里插入图片描述

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

class not found:ClassTest

执行UserDaoTest的test方法之前,要先 mvn test-compile 生成 test classes才可被部署并发现

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

Type interface com.kuang.dao.UserDao is not known to the MapperRegistry
<!-- 每一个Mapper.xml都需要在MyBatis核心配置文件中注册 -->
<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>
Could not find resource com/kuang/dao/UserMapper.xml

Maven约定大于配置,自己写的配置文件默认不会被导出或生效

Maven默认的资源(自己配置的xml)位置在resources目录下,当前项目的xml位于java目录下,所以找不到

在这里插入图片描述

<!-- build中配置resources,防止资源导出失败问题 -->
<build>
    <resources>
        <resource>
            <!-- 使得directory目录下的资源可以被导出 -->
            <directory>src/main/java</directory>
            <!-- 设置可被识别通过的文件类型 -->
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>

        <resource>
            <!-- 使得directory目录下的资源可以被导出 -->
            <directory>src/main/resources</directory>
            <!-- 设置可被识别通过的文件类型 -->
            <includes>
                <include>**/*.propertes</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

终于成功

在这里插入图片描述

增删改查CRUD

CUD 需要通过connection对象以Transition(事务)的形式提交

  1. 编写接口
  2. (实现接口)编写mapper中对应的sql语句
  3. 测试

select

选择,查询语句:

  • id:方法名
  • resultType:Sql语句执行的返回值
  • parameterType:参数类型

通过id获取用户

  1. 在这里插入图片描述

  2. 在这里插入图片描述

  3. 在这里插入图片描述

模糊查询

在这里插入图片描述

  1. Java代码执行时,传递通配符 %%

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

  2. 在sql语句拼接中使用通配符

    • 存在sql注入的风险

    在这里插入图片描述

    在这里插入图片描述

insert

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

并没有新增

在这里插入图片描述

更新

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

删除

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

参数传递&Map

单个参数传递方式
  • 只有一个 基本数据类型 ,可省略
  • 实体类对象作为参数,sql语句中的参数取对象的属性
  • Map作为参数,sql语句中参数取Map的属性
多个参数的传递
使用Map的情况

当字段过多时,考虑使用 Map,可以自定义需要传递的参数

  • 若使用实体类作为参数传递,当字段过多时,一个实体类的每个属性都必须设置值
  1. 在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  2. 在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

Plugin——通用Mapper

在这里插入图片描述

核心配置——mybatis-config.xml

configuration(配置)

属性(properties)

通过Properties引用配置文件

  • 优先使用外部配置文件
  1. properties文件定义属性的键值对——定义变量
#db.properties
mysql_driver=com.mysql.cj.jdbc.Driver
#不需要转义&amp;
MyBatis_url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
db_username=root
db_pwd=2017002231
  1. 通过 <properties/> 声明引用属性

    在这里插入图片描述

    <!-- properties引用属性变量 -->
    <properties resource="db.properties"/>
    
  2. 使用属性
    在这里插入图片描述

设置Settings

SettingDescriptionValid ValuesDefault
cacheEnabled是否缓存Globally enables or disables any caches configured in any mapper under this configuration.true | falsetrue
lazyLoadingEnabled懒加载,提高开发效率When enabled, all relations will be lazily loaded. This value can be superseded for a specific relation by using the fetchType attribute on it.true | falsefalse
mapUnderscoreToCamelCaseEnables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn.true | falsefalse
logImplMyBatis的日志实现方式Specifies which logging implementation MyBatis should use.LOG4J|STDOUT_LOGGINGNo Set
日志实现——logImpl
  • SLF4J
  • LOG4J | LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING
  • NO_LOGGING
STDOUT_LOGGING
<!--设置日志实现方式-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

在这里插入图片描述

  • 由日志可见,MyBatis底层是基于JDBC实现的
LOG4J
  • 控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等
  • 控制每一条日志的输出格式
  1. 导入 LOG4J

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  2. 配置log4j.properties资源

# 将等级为DEBUG的日志信息输出到console和file两个目的地,console和file的定义在下面的代码
log4j.rootLogger = debug,console,file

# 控制台处处的相关配置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

# 文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = ./logs/log.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

# 日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

在这里插入图片描述

程序中使用log4j
  1. 导包

    import org.apache.log4j.Logger;
    
  2. 设置变量

    static Logger logger = Logger.getLogger(UserMapperTest.class);
    

    Logger.getLogger(className):将日志对象与目标对象绑定

  3. 使用

    log级别

    • info([信息])
    • debug([信息])
    • error([信息])

    在这里插入图片描述

环境配置 enviroments

MyBatis 可以配置成适应多种环境,但每个 SqlSessionFactory 实例只能选择一种环境

如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。

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

两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”)

  • 使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
数据源(dataSource)

连接数据库:

  • jdbc
  • dbcp
  • c3p0
  • druid

三种数据源类型

  1. UNPOOLED——用完即销毁

    • 无连接池,每次请求时打开和关闭连接

    • 浪费资源

  2. POOLED——用完即回收

  3. JNDI

类型别名typeAliases

用于减少完全限定名的冗余给Bean取别名

配置方式
  1. 实体类较少,可逐一指定

    <!-- mybatis-config.xml -->
    <typeAliases>
        <typeAlias type="com.kuang.pojo.User" alias="User"/>
    </typeAliases>
    
    <!-- UserMapper.xml -->
    <mapper namespace="com.kuang.mapper.UserMapper">
        <!--id:方法名-->
        <select id="getUserList" resultType="User">
            select *from mybatis.user;
        </select>
    </mapper>
    
  2. You can also specify a package where MyBatis will search for all beans.包中实体类的别名为 lowercase(类名的首字母)

    <!-- mybatis-config.xml -->
    <typeAliases>
        <package name="com.kuang.pojo" />
    </typeAliases>
    
    <!-- UserMapper.xml -->
    <mapper namespace="com.kuang.mapper.UserMapper">
        <!--id:方法名-->
        <select id="getUserList" resultType="user">
            select *from mybatis.user;
        </select>
    </mapper>
    
  3. If the @Alias annotation is found its value will be used as an alias. 优先级 :注解别名>配置别名

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

MyBatis默认配置的别名
AliasMapped Type
_普通数据类型普通数据类型(int,short,long,byte,double,float,boolean)
小写首字母(数据类型名)首字母大写的数据类型(基本数据类型 + Date,Object,Map,HashMap,List,ArrayList,Collection,Iterator)
Integer,intBigDecimal
decimal,bigdecimalInteger

插件plugins

  • mybatis-generator-core

  • mybatis-plus

    在这里插入图片描述

  • 通用mapper

映射器mapper

接口实现(mapper.xml)必须在configuration中注册才可被发现

第一种方式:资源路径【推荐】

<!-- Using classpath relative resources -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

第二种方式:类名

<!-- Using mapper interface classes -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

第三种方式:包内全导入

<!-- Register all interfaces in a package as mappers -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

第二、三种方式的问题

  • 接口和Mapper配置文件必须同名
  • 接口和Mapper配置资源必须在同一包下

Mapper.xml(Dao实现类)

  • resultMap – The most complicated and powerful element that describes how to load your objects from the database result sets.
    • javaType:class——POJO| ArrayList
    • ofType:list 或 set 中的POJO
  • insert – A mapped INSERT statement.
  • update – A mapped UPDATE statement.
  • delete – A mapped DELETE statement.
  • select – A mapped SELECT statement.

解决属性名和字段名不一致问题——resultMap

简单的例子

public class User {
    private Integer id;
    private String user_name;
    private String password;
}

在这里插入图片描述

解决思路:起别名

sql 中,用 as 关键字,可以给某一字段起别名

select *from user where id=#{id}

select
	id as id,
    user_name as user_name,
    pwd as password
from user where id=#{id};

Mybatis 中,使用 ResultMap 做结果映射,只需要将有差异的属性与字段映射即可

在这里插入图片描述

  • property:POJO中的属性
  • column:数据库中的字段

复杂查询

实体间的复杂关系&环境搭建

关联association:多对一

  • 查到的是结果是满足某种关系的个体集

集合collection:一对多

  • 返回的结果是一个个体,其中某个属性是个体集

在这里插入图片描述

create table teacher(
	id int(10) not null,
    user_name varchar(30) default null,
    primary key(id)
)engine=InnoDB default charset=utf8;

insert into teacher(id,user_name) values(1,'秦老师');
insert into teacher(id,user_name) values(2,'江老师');

create table student(
	id int(10) not null,
    user_name varchar(30) default null,
    tid int(10) default null,
    primary key (id),
    key fktid(tid),
    constraint fktid foreign key (tid) references teacher(id)
)engine=InnoDB default charset=utf8;

insert into student(id,user_name,tid) values(1,"小明",1);
insert into student(id,user_name,tid) values(2,"小红",2);
insert into student(id,user_name,tid) values(3,"小张",1);
insert into student(id,user_name,tid) values(4,"小李",1);
insert into student(id,user_name,tid) values(5,"小王",2);
  1. 导入lombok
  2. 新建实体类
  3. 建立Mapper接口
  4. 建立Mapper.xml资源
  5. 在核心配置文件中绑定注册Mapper
  6. 测试查询成功
Association
联表查询

在这里插入图片描述

select s.id as sid,s.user_name as sname,t.id as tid,t.user_name as tname
from student as s,teacher as t
where s.tid=t.id

在这里插入图片描述

  1. 接口

    List<Student> getStudent2();
    
  2. 接口实现

    <!--BFS:联表查询,处理结果-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id as sid,s.user_name as sname,t.id as tid,t.user_name as tname
        from student as s,teacher as t
        where s.tid=t.id
    </select>
    
    <resultMap id="StudentTeacher2" type="student">
        <result property="id" column="sid"/>
        <result property="user_name" column="sname"/>
        <association property="teacher" javaType="teacher">
            <result property="id" column="tid"/>
            <result property="user_name" column="tname"/>
        </association>
    </resultMap>
    
  3. 测试

    在这里插入图片描述

嵌套查询
select *
from student as s
where s.tid 
in (select t.id from teacher as t);

在这里插入图片描述

  1. 定义接口

    //查询学生对应的老师信息
    List<Student> getStudent();
    
  2. 实现接口

    <!--思路:DFS 查询嵌套,
    	1. 查询所有学生信息
        2. 根据查出来学生的tid,查找对应的teacher
    -->
    <select id="getStudent" resultMap="StudentTeacher">
        select *from mybatis.student;
    </select>
    
    <resultMap id="StudentTeacher" type="student">
        <!--
    		简单属性用 <result property="" column=""/>映射即可
     	-->
    
        <!--复杂属性
            多对*————关联association
    		一对*————集合collection
         -->
        <association property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
    </resultMap>
    
    <select id="getTeacher" resultType="teacher">
        select *from mybatis.teacher where id=#{tid};
    </select>
    
  3. 在这里插入图片描述

Collection
@Data
public class Student {
    private Integer id;
    private String user_name;
    private Integer tid;
}

@Data
public class Teacher {
    private Integer id;
    private String user_name;

    //一个老师拥有多个学生
    private List<Student> students;
}

实现根据teacher.id查找该老师对应的所有学生

在这里插入图片描述

联表查询
select t.id tid,t.user_name tname, s.id sid,s.user_name sname
from teacher t,student s
where t.id=s.tid and t.id=1;

在这里插入图片描述

  1. 定义接口

    //获取某个老师下所有的学生信息
    Teacher getTeacherById(@Param("tid") Integer id);
    
  2. 实现接口

    <select id="getTeacherById" resultMap="StudentTeacher">
        select t.id tid,t.user_name tname, s.id sid,s.user_name sname
        from teacher t,student s
        where t.id=s.tid and t.id=#{tid};
    </select>
    <resultMap id="StudentTeacher" type="Teacher">
        <result property="id" column="tid"/>
        <result property="user_name" column="tname"/>
        <!-- 集合中的泛型用ofType指定 -->
        <collection property="students" ofType="student">
            <result property="id" column="sid"/>
            <result property="user_name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    
  3. 测试

    在这里插入图片描述

嵌套查询
select tid,(select user_name from teacher where id=1) tname,id sid,user_name sname
from student s
where tid=1;

在这里插入图片描述

  1. 定义接口

    Teacher getTeacherById2(@Param("tid") Integer id);
    
  2. 实现接口

    <select id="getTeacherById2" resultMap="StudentTeacher2">
        select *from mybatis.teacher where id=#{tid}
    </select>
    <resultMap id="StudentTeacher2" type="teacher">
        <collection property="students" column="id" javaType="ArrayList" ofType="student" select="GetStudentByTid" />
    </resultMap>
    <select id="GetStudentByTid" resultType="student">
        select *
        from mybatis.student
        where tid=#{tid};
    </select>
    
  3. 测试

    在这里插入图片描述

动态sql

根据不同的条件生成不同的sql语句

搭建环境
create table blog(
	id varchar(50) not null comment '博客id',
    title varchar(100) not null comment '博客标题',
    author varchar(30) not null comment '博客作者',
    create_time datetime not null comment '创建时间',
    views int(30) not null comment '浏览量'
)engine=InnoDB default charset=utf8;
@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private Integer views;
}
@SuppressWarnings("all")//抑制所有警告
public class TestBlog {
    @Test
    public void test(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

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

        Blog blog = new Blog();
        blog.setId(IDUtil.getId());
        blog.setAuthor("kuang");
        blog.setTitle("MyBatis如此简单!");
        blog.setCreateTime(new Date());
        blog.setViews(9999);
        mapper.insert(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("Java如此简单!");
        blog.setViews(9999);
        mapper.insert(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("Spring如此简单!");
        mapper.insert(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("微服务如此简单!");
        mapper.insert(blog);

        sqlSession.close();
    }
}
查询
IF

在这里插入图片描述

  1. 接口

    //查询blog信息
        List<Blog> queryBlogIF(Map map);
    
  2. 接口实现

    <select id="queryBlogIF" resultType="blog" parameterType="map">
        select *from mybatis.blog where 1=1
        <if test="title!= null">
            and titie=#{title}
        </if>
        <if test="author!= null">
            and author = #{author}
        </if>
    </select>
    
  3. 测试

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

where优化
<select id="queryBlogIF" resultType="blog" parameterType="map">
    select *from mybatis.blog
    <where>
        <if test="title!= null">
            title=#{title}
        </if>
        <if test="author!= null">
            and author = #{author}
        </if>
    </where>
</select>
  • The where element knows to only insert “WHERE” if there is any content returned by the containing tags. (满足条件插入)
  • Furthermore, if that content begins with “AND” or “OR”, it knows to strip it off.(保证第一个 where前没有逻辑判断)
choose-when-otherwise&where

switch-case-default | if-else if - else

  1. 定义接口

    List<Blog> queryBlogIF1(Map map);
    
  2. 实现接口

    <select id="queryBlogIF1" parameterType="map" resultType="blog">
    	select *from mybatis.blog
        <where>
        	<choose>
                <when test="id!=null">
                    id=#{id}
                </when>
            	<when test="title != null">
                	title=#{title}
                </when>
                <when test="author != null">
                	author=#{author}
                </when>
                <otherwise>
                	views>1000
                </otherwise>
            </choose>
    	</where>
    </select>
    
  3. 测试

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

更新
set
  • The set element can be used to dynamically include columns to update, and leave out others.(选目标字段,删除无关字符)
    • the set element will dynamically prepend the SET keyword,(前置)
    • and also eliminate any extraneous commas that might trail the value assignments after the conditions are applied.(删逗号)
  1. 定义接口

    //更新信息
    int updateBlog(Map map);
    
  2. 实现接口

    <update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title!=null">title=#{title},</if>
            <if test="author!=null">author=#{author},</if>
            <if test="views!=null">views=#{views},</if>
            create_time =#{createTime}
        </set>
        where id=#{id}
    </update>
    
  3. 测试

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

trim替换

前缀后缀都是 prefix,XXOverrides决定替换的位置

<select id="queryBlogIFByTrim" resultType="blog" parameterType="map">
    select *from mybatis.blog
    <trim prefix="where" prefixOverrides="and |or ">
        <if test="title!= null">
            title=#{title}
        </if>
        <if test="author!= null">
            and author = #{author}
        </if>
    </trim>
</select>
  • The prefixOverrides attribute takes a pipe delimited list of text to override, where whitespace is relevant.前缀Overrides 属性采用管道分隔文本列表来重写,其中空白是相关的。(最好写上,替换后可能会出问题)
    • The result is the removal of anything specified in the prefixOverrides attribute
    • and the insertion of anything in the prefix attribute
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
sql片段

公共部分抽取出来,方便复用

  • <sql id=""></sql> 抽取
  • <include refid="" /> 引用
<sql id="if-title-author">
    <if test="title!= null">
        title=#{title}
    </if>
    <if test="author!= null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIFByTrim" resultType="blog" parameterType="map">
    select *from mybatis.blog
    <trim prefix="where" prefixOverrides="and |or ">
        <include refid="if-title-author" />
    </trim>
</select>
  • 基于单表查询
  • 不要存在 <where> 标签
foreach

sql in 的动态范围查询

select *from user where 1=1 and 

(id=1 or id=2 or id=3);

<foreach item="item" collection="ids" open="(" separator=" or " close=")">
    #{item}
</foreach>
  • open:开始符
  • separator:分隔符
  • close:结束符
  • item:项
  • colloetion:遍历集合
  1. 定义接口

    List<Blog> queryBlogIn(Map map);
    
  2. 实现接口

    <select id="queryBlogIn" parameterType="map" resultType="blog">
        select *from mybatis.blog
        <where>
            <foreach collection="ids" item="id" open="(" separator="or" close=")">
                id=#{id}
            </foreach>
        </where>
    </select>
    
  3. 测试

    在这里插入图片描述

分页

limit实现分页
sql语句
select *from [table_name] limit [offset],[limit];

# [offset]缺省,默认从0开始,到[end]
select *from [table_name] limit [end];
MyBatis方式
  1. 接口

    //分页查询用户信息
    List<User> getUserWithLimit(Map<String,Integer> map);
    
  2. 接口配置

    <select id="getUserWithLimit" resultMap="UserMap" resultType="user" parameterType="map">
        select *from mybatis.user limit #{offset},#{limit};
    </select>
    
  3. 测试

    @Test
    public void testGetUserWithLimit(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    	
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("offset",1);
        map.put("limit",2);
        List<User> userList = mapper.getUserWithLimit(map);
    
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    
RowBounds实现分页[不建议使用]

不在sql进行分页,通过sqlSession对象实现分页——RowBounds

  1. 接口

    List<User> getUserWithLimit2();
    
  2. 配置Mapper

    <select id="getUserWithLimit2" resultMap="UserMap" resultType="user">
        select *from mybatis.user;
    </select>
    
  3. 测试

    @Test
    public void testGetUserWithLimit2(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        RowBounds rowbounds = new RowBounds(1,2);
        List<User> userList = sqlSession.selectList("com.kuang.mapper.UserMapper.getUserWithLimit2",null,rowbounds);
    
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    
插件——pageHelper

在这里插入图片描述

缓存

简介

问题:连接数据库消耗资源

解决:一次查询,保存到高速存储——> 内存

缓存:

  • 放在内存中的临时数据
  • 经常查询且不常改变 的数据存放在缓存,直接从服务器内存取比从服务器磁盘IO速度快,提高查询效率,解决高并发系统的性能问题

使用缓存,减少与数据库交互次数,减少系统开销,提高系统效率

缓存merCached缓存服务器
读写分离,主从复制
MyBatis缓存

系统默认定义两级缓存:一级缓存和二级缓存

  • 一级缓存:SqlSession级,本地缓存
  • 二级缓存:手动开启和配置,namespace级缓存
  • MyBatis自定义缓存接口Cache,通过实现接口自定义二级缓存
一级缓存——Map

一级缓存默认开启,在一次SESSION期间有效

  1. 开启日志

  2. 测试一个Session中查询两次相同记录

    @Test
    public void test(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
    
        System.out.println("====================");
        User user2 = mapper.getUserById(1);
        System.out.println(user2);
    
        System.out.println(user1==user2);
    
        sqlSession.close();
    }
    
  3. 查看日志输出

    两次查找一次查表

    在这里插入图片描述

    两次结果引用同一对象

缓存失效
  • R不同的东西

  • CUD必定刷新缓存

    在这里插入图片描述

  • 不同的Mapper

  • 手动清理缓存

    在这里插入图片描述

二级缓存

工作机制:

一个Session期间的数据会被放到一级缓存,当Session关闭或提交,对应的一级缓存中的数据被保存到二级缓存中

  • 新的Session查询信息,从二级缓存中获取内容
  • 不同的mapper查出的数据会放到自己对应的缓存中
  1. mybatis-config.xml 开启二级缓存

    <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
    
  2. 配置mapper.xml

    <!--在当前mapper中使用二级缓存-->
    <cache
      eviction="FIFO"
      flushInterval="60000"
      size="512"
      readOnly="true"/>
    
    • mapper.xml中的所有 select 语句的结果将会被缓存。
    • mapper.xml中的所有 insert、update 和 delete 语句会刷新缓存。
    • eviction:替换策略
      • LRU:默认
      • FIFO
    • flushInterval:刷新间隔
      • 以毫秒为单位
      • 不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新
    • size:引用数目
      • 默认值是 1024
    • readOnly:只读
      • 只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改
      • 可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false
  3. 测试

    在这里插入图片描述

  4. 问题

    • 将实体类序列化,否则保错
    java.io.NotSerializableException: com.kuang.pojo.User
    
    package com.kuang.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.io.Serializable;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User implements Serializable {
    	private Integer id;
    	private String user_name;
    	private String pwd;
    }
    
缓存原理

在这里插入图片描述

查找顺序:

  1. 二级缓存
  2. 一级缓存
  3. 数据库
@Test
public void test(){
    SqlSession sqlSession1 = MyBatisUtils.getSqlSession();

    User user1 = sqlSession1.getMapper(UserMapper.class).getUserById(1);
    System.out.println(user1);
    sqlSession1.close();

    SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
    User user2 = sqlSession2.getMapper(UserMapper.class).getUserById(1);
    System.out.println(user2);
    sqlSession2.close();

    System.out.println(user1==user2);

    SqlSession sqlSession3 = MyBatisUtils.getSqlSession();
    User user3 = sqlSession3.getMapper(UserMapper.class).getUserById(2);
    System.out.println(user3);
    sqlSession3.close();
}

在这里插入图片描述

  • 由Cache Hit Ratio的计算,可知cache机制是先查二级缓存,再数据库
自定义缓存——Ehcache

开源Java分布式缓存

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.1.0</version>
</dependency>
<!--mapper.xml-->
<cache type="com.domain.something.MyCustomCache"/>
public interface Cache {
  String getId();
  int getSize();
  void putObject(Object key, Object value);
  Object getObject(Object key);
  boolean hasKey(Object key);
  Object removeObject(Object key);
  void clear();
}

在这里插入图片描述

注解开发

面向接口编程

目的:解耦

接口的理解
  • 定义实现 分离
  • 接口反映系统设计人员对系统的抽象理解
  • 接口分类:
    • 一个个体的抽象——抽象体(abstract class)
    • 一个个体的某一方面的抽象——抽象面(Interface)
  • 接口设计更多体现对系统整体的架构

使用注解开发

本质:反射机制

底层:动态代理

Java Annotations are both limited and messier for more complicated statements.

  1. 注解在接口上实现

    public interface UserMapper {
        @Select("select *from user")
        List<User> getUsers();
    }
    
  2. 绑定接口

    <!--mybatis-config.xml-->
    <!-- 绑定接口 -->
    <mappers>
        <mapper class="com.kuang.mapper.UserMapper"/>
    </mappers>
    
  3. 测试

    @Test
    public void test(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
    
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    

    在这里插入图片描述

参数

当有多个参数,基本数据类型或String的参数前加注解 @param关联参数

引用类型不需要加

sql中使用的是@Param()中设定的属性名

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

#{} 与 ${} 的区别
  • ${}是字符串替换,,Mybatis 在处理${}时,就是把他替换成变量的值
  • #{}是预编译处理,会将 #{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
  • 使用#{}可以有效的防止 SQL 注入,提高系统安全性
自动提交事务
public class MyBatisUtils{
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }
}
CRUD
Create
//UserMapper.java
public interface UserMapper{
    @Insert("insert into user(id,user_name,pwd) values(#{id},#{user_name},#{pwd})")
int insertUser(User user);
}

在这里插入图片描述

Update
//UserMapper.java
public interface UserMapper{
    @Update("update user set user_name=#{user_name},pwd=#{pwd} where id=#{id}")
    int updateUser(User user);
}

在这里插入图片描述

POJO方法的简化——Lombok
  1. IDEA中安装插件

  2. 项目中导入依赖

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
        <scope>provided</scope>
    </dependency>
    
  3. 使用注解简化

    @Getter and @Setter
    @ToString
    @EqualsAndHashCode
    @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
    @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
    @Data
    
    • @Data,@AllArgsConstructor,@NoArgsConstructor

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

MybatisPlus

简介

在MyBatis基础上,只做增强不做改变,为简化开发、提高效率而生

  • 无侵入
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • CRUD:内置通用 Mapper、通用 Service
  • 支持主键自动生成
  • 支持 XML 热加载 :Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
  • 支持 ActiveRecord 模式
  • 支持自定义全局通用操作:支持全局通用方法注入
  • 内置代码生成器 :采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎
  • 内置分页插件 、性能分析插件
  • 全局拦截(提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作)
  • 内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击

MtbatisPlus架构

在这里插入图片描述

通过简单语句,生成SQL语句,交给MyBatis执行

使用

1. 建库建表

创建数据库 haoke

在这里插入图片描述

use haoke;

CREATE TABLE `user` (
	`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
	`name` varchar(30) DEFAULT NULL COMMENT '姓名',
	`age` int(11) DEFAULT NULL COMMENT '年龄',
	`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 插入数据
INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('1', 'Jone', '18','test1@baomidou.com');
INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('2', 'Jack', '20','test2@baomidou.com');
INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('3', 'Tom', '28','test3@baomidou.com');
INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('4', 'Sandy', '21','test4@baomidou.com');
INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('5', 'Billie', '24','test5@baomidou.com');

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

2. 创建工程及导入依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!--mybatis-plus的springboot支持-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.2</version>
    </dependency>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
3. 编写application.properties文件
spring.application.name = mybatis-plus
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://8.140.130.91:3306/haoke?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
4. 创建User对象
package com.mybatisplus.pojo;

public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    public User() {
    }

    public User(Long id, String name, Integer age, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
5. 编写UserMapper
package com.mybatisplus.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {

}
6. 编写SpringBoot启动类
package com.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.mybatisplus.mapper") //设置mapper接口的扫描包
@SpringBootApplication
public class Myapplication {
    public static void main(String[] args) {
        SpringApplication.run(Myapplication.class,args);
    }
}
7. 编写SpringBoot启动类
package com.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.mybatisplus.mapper") //设置mapper接口的扫描包
@SpringBootApplication
public class Myapplication {
    public static void main(String[] args) {
        SpringApplication.run(Myapplication.class,args);
    }
}
8. 编写单元测试用例
package com.mybatisplus;

import com.mybatisplus.mapper.UserMapper;
import com.mybatisplus.pojo.User;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void test(){
        System.out.println("-------selectAll method test-------");

        List<User> users = userMapper.selectList(null);

        for (User user : users) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

通用Mapper

在MybatisPlus中,BaseMapper中定义了一些常用的CRUD方法,当我们自定义的Mapper接口继承BaseMapper后即可拥有了这些方法 【这些方法仅适合单表操作】

/**
 * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
 */
public interface BaseMapper<T> extends Mapper<T> {

    /**
     * 插入一条记录
     *
     * @param entity 实体对象
     */
    int insert(T entity);

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    int deleteById(Serializable id);

    /**
     * 根据 columnMap 条件,删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,删除记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 删除(根据ID 批量删除)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

    /**
     * 根据 ID 修改
     *
     * @param entity 实体对象
     */
    int updateById(@Param(Constants.ENTITY) T entity);

    /**
     * 根据 whereEntity 条件,更新记录
     *
     * @param entity        实体对象 (set 条件值,可以为 null)
     * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    T selectById(Serializable id);

    /**
     * 查询(根据ID 批量查询)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

    /**
     * 查询(根据 columnMap 条件)
     *
     * @param columnMap 表字段 map 对象
     */
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,查询一条记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     * <p>注意: 只返回第一个字段的值</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件
     * @param queryWrapper 实体对象封装操作类
     */
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
通过id查询——selectById
@Test
public void testSelectById(){
    System.out.println("通过Id查询");
    User user = userMapper.selectById(3L);//数据类型为Long,id为3

    System.out.println(user);
}

在这里插入图片描述

模糊查询——like

在这里插入图片描述

条件查询

在这里插入图片描述

https://mp.baomidou.com/guide/wrapper.html#abstractwrapper

插入数据
@Test
public void testSave(){
    User user = new User();
    user.setAge(25);
    user.setEmail("zhangsan@qq.com");
    user.setName("zhangsan");
    int count = userMapper.insert(user);
    System.out.println("新增数据成功! count=>"+count);
}
id自增问题

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

所以自增问题出现在java参数传递中

public class User {
    
    @TableId(value = "ID", type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

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

删除数据

在这里插入图片描述

修改数据

根据id修改,只修改指定的字段

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

分页查询
/**
 * 分页插件
 */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
    // paginationInterceptor.setOverflow(false);
    // 设置最大单页限制数量,默认 500 条,-1 不受限制
    // paginationInterceptor.setLimit(500);

    PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
    paginationInnerInterceptor.setDbType(DbType.MYSQL);

    interceptor.addInnerInterceptor(paginationInnerInterceptor);
    return interceptor;
}

在这里插入图片描述

配置

使用MyBatis原生配置文件

# 指定全局配置文件
mybatis-plus.config-location = classpath:mybatis-config.xml
# 指定mapper.xml文件
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml

若指定配置文件,无需配置环境,只需要

<?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">
<!-- configuration的核心配置 -->
<configuration>
    <!-- 每一个Mapper.xml都需要在MyBatis核心配置文件中注册 -->
</configuration>

https://mp.baomidou.com/guide/config.html#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE

Lombok

  • @Data:注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
  • @Setter:注解在属性上;为属性提供 setting 方法
  • @Getter:注解在属性上;为属性提供 getting 方法
  • @Slf4j:注解在类上;为类提供一个 属性名为log 的 slf4j日志对象
  • @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
  • @AllArgsConstructor :注解在类上;为类提供一个全参的构造方法
  • @Builder :使用Builder模式构建对象

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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AmosTian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值