初识MyBatis

40 篇文章 3 订阅
11 篇文章 0 订阅

初识MaBatis

image-20220909084940500

前言

本文是博主初步学习MyBatis所做的笔记🌞,当中如有错别字、描述不对的地方或着侵权的地方,恳请及时告知,博主亦会虚心接收,及时更正😃

  • 博主主页:知识汲取者
  • 博主Gitee仓库:Gitee
  • 博主Github仓库:Github

欢迎大家访问支持<(^-^)>

1、MaBatis概述

  • Mabatis是什么

      MyBatis 是一款优秀的持久层1框架2(也是一个半自动的ORM,Object Relation Mapping框架),它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

    官网mybatis – MyBatis 3 | 简介

  • Mabatis的优点

    1)提高代码的可维护性。Mabatis让SQL语句和代码进行了解耦3,SQL语句写在XML文件中想修改SQL语句只需要修改XML文件而不必去修改代码

    2)减少重复代码。与JDBC相比,减少了50%以上的代码量,消除了JDBC 大量冗余的代码,不需要手动开关连接

    3)具有良好的兼容性。因为MyBatis 使用JDBC 来连接数据库,所以只要JDBC 支持的数据库MyBatis 都支持

    4)简单易学。本身就很小且简单,没有任何第三方依赖,最简单安装只要两个jar文件+配置几个SQL映射文件。

    5)灵活轻便。MyBatis不会对应用程序或者数据库的现有设计强加任何影响。 SQL语句写在XML文件里,便于统一管理和优化。通过SQL语句可以满足操作数据库的所有需求。PS:MyBatis还具有强大的动态SQL能力

    ……

  • Mabatis的历史

      MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。

拓展:JavaEE的三层架构

  • 表现层:用于展示数据
  • 业务层:用于处理业务逻辑
  • 持久层:用于将数据保存到数据库

2、MyBatis快速入门

任务:使用MyBatis读取数据库中的User表中的所有数据,并以日志文件的形式打印到控制台上

准备工作
  • Step1:在数据库中创建User表

    create database mybatis;
    use mybatis;
    
    drop table if exists tb_user;
    
    create table tb_user(
    	id int primary key auto_increment,
    	username varchar(20),
    	password varchar(20),
    	gender char(1),
    	addr varchar(30)
    );
    INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
    INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
    INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
    
  • Step2:创建Maven项目模块

    image-20220725203145197

  • Step3:定义POJO4(Plain Ordinary Java Object)类

    User类:

    package com.hhxy.pojo;
    
    public class User {
        private Integer id;
        private String username;
        private String password;
        private String gender;
        private String addr;
    
        public User() {
        }
    
        public User(Integer id, String username, String password, String gender, String addr) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.gender = gender;
            this.addr = addr;
        }
    
        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 String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public String getAddr() {
            return addr;
        }
    
        public void setAddr(String addr) {
            this.addr = addr;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", gender='" + gender + '\'' +
                    ", addr='" + addr + '\'' +
                    '}';
        }
    }
    
正式开始
编写Maven配置文件
pom.xml
编写MyBatis核心配置文件
mybatis-config.xml
编写SQL映射文件
UserMapper.xml
编写Logback核心配置文件
logback.xml
编写相关Java代码

备注

  1. 编写Maven配置文件,主要是用来导入项目所依赖的jar包
  2. 编写MyBatis核心配置文件,主要是实现MaBatis框架的核心功能,包括数据库连接、关联SQL映射文件(暂时先不管,后续深入了解)需要注意:该配置文件的名字一定不能乱改!!!
  3. 编写SQL映射文件,该文件中存放Java代码要执行的SQL语句,实现了SQL语句和代码进行了解耦
  4. 编写Logback核心配置文件,主要是用于方便查看使用MyBatis框架执行程序后的具体细节

这些配置文件的编写顺序没有要求但是配置文件的编写肯定是要在编写Java代码前的 (其实这些文件CV一下就行了😆)

推荐阅读:

  1. 一文带你快速上手Maven
  2. Logback快速入门
  • Step1:编写Maven配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.hhxy</groupId><!--包名-->
        <artifactId>day3_mybatis</artifactId><!--模块名-->
        <version>1.0-SNAPSHOT</version>
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <!--使用坐标导入项目依赖的jar包-->
        <dependencies>
            <!-- mybatis依赖jar包导入 -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.5</version>
            </dependency>
            <!-- mysql驱动jar包导入 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.27</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13</version>
                <scope>test</scope>
            </dependency>
            <!--logback相关的jar包导入-->
            <!-- 1.添加slf4j日志api -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.20</version>
            </dependency>
            <!-- 2.添加logback-classic依赖 -->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!-- 3.添加logback-core依赖 -->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
        </dependencies>
    </project>
    
  • Step2:编写MyBatis核心配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--MyBatis核心配置文件-->
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <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:///mybatis?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="32345678"/>
                </dataSource>
            </environment>
        </environments>
        <!--指定SQL映射文件-->
        <mappers>
            <mapper resource="UserMapper.xml"/>
        </mappers>
    </configuration>
    
  • Step3:编写SQL映射文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--Mybatis中的SQL映射文件,用于书写SQL语句-->
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="test">
        <!--
        namespaace:名称空间,不能为空
        resultType:返回的结果类型
    	一般我们也将select标签这一块称作一个statement
        -->
        <select id="selectAll" resultType="com.hhxy.pojo.User">
        select * from tb_user;
      </select>
    </mapper>
    
  • Step4:编写Logback核心配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <!--
            CONSOLE :表示当前的日志信息是可以输出到控制台的。
        -->
        <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
            </encoder>
        </appender>
    
        <logger name="com.itheima" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!--
          level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
         , 默认debug
          <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
          -->
        <root level="DEBUG">
            <appender-ref ref="Console"/>
        </root>
    </configuration>
    
  • Step5:编写相关Java代码

    加载MyBatis核心文件
    获取SqlSessionFactory对象
    获取SqlSession对象
    执行SQL映射文件中SQL语句
    释放资源
    package com.hhxy.test;
    
    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 java.io.InputStream;
    import java.util.List;
    
    public class MyBatisDemo {
        public static void main(String[] args) throws Exception {
            //1、定位xml文件,获取SqlSessionFactory对象
            String resource = "./mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //2、获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //3、执行SQL语句
            List<Object> users = sqlSession.selectList("test.selectAll");
    
            System.out.println(users);
            //5、释放资源
            sqlSession.close();
        }
    }
    

拓展:IDEA设置数据库连接(用于解决SQL映射文件的警告提示 警告提示后没有关键字提示了,用起来很不方便

image-20220725211718876 image-20220725213351025 image-20220725213542474
  • 当鼠标选中mybatis@localhost时,点击🖊可以直接在IDEA中书写SQL语句,比在Navicat中写SQL更舒服,因为IDEA有更强大的关键字提示😃
  • 当鼠标选中表时,点击🖊可以直接设计表

IDEA真的很🐂( ఠൠఠ )ノ

3、Mapper代理

  通过MyBatis快速入门,我们可以知道MyBatis优化了原生JDBC的硬编码问题5,但是它的优化不够彻底,当我们使用MyBatis执行SQL语句时,仍然存在硬编码问题,这就需要使用到Mapper代理来进行进一步优化了。

  Mapper代理就是定义一个接口,在接口中定义和SQL映射文件的SQL语句相关联的抽象方法,从而在Java代码中只需要使用该接口对象中的方法就能直接访问SQL映射文件,而不需要再通过文件路径来访问SQL映射文件。

Mapper代理的优点

  1. 提高代码的移植性。Mapper代理进一步优化了原生MyBatis访问SQL映射文件存在的硬编码问题
  2. 使用简单。IDEA可以直接补全接口中的方法名,不需要像之前一样要自己手写文件路径

示例

编写Mapper接口
UserMapper
编写MyBatis所需的配置文件
编写Java代码

注意

  1. Mapper接口最好和相应的SQL映射文件同名,同时要和SQL映射文件在同一目录下

    如果Mapper接口和SQL映射文件同名,可以使用包扫描的方式进化SQL映射文件的加载

  2. Mapper接口中的方法名要和SQL映射文件中中SQL语句标签的id属性值同名,并且参数类型和返回值类型要相同

  3. SQL映射文件中mapper标签的namespace属性值要和Mapper接口的全类名相同


小知识须知:在Maven项目中,按照Maven规范,我们必须将代码(类、接口)和配置文件分开写,但是Mapper接口有需要和SQL映射文件在同一级目录下,就需要利用Maven项目编译的特点,即:当Maven项目被编译后,resources区域的文件和Java代码区域的文件是放在在一个区域进行管理的(可以使用compile命令后,去文件夹中查看验证),这样我们就可以只需要给JMapper接口和其相应的SQL映射文件设置相同的目录结构就可以解决这个问题了。同时需要注意,resources区域是文件目录,不能通过点直接创建目录结构,必须一个一个地进行创建(或者使用/号),而Java代码区域可以直接使用点创建目录结构

image-20220726204710733
package com.hhxy.test;

import com.hhxy.mapper.UserMapper;
import com.hhxy.pojo.User;
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 java.io.InputStream;
import java.util.List;

public class MyBatisDemo {
    public static void main(String[] args) throws Exception {
        //1、定位xml文件,获取SqlSessionFactory对象
        String resource = "./mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //2、获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        /*---------------------------------Mapper代理核心代码--------------------------------*/
        //3、执行SQL语句
        //3.1 获取UserMapper接口对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //3.2 获取SQL语句执行后的返回对象
        List<User> users = userMapper.selectAll();
        //这段代码的原生写法:List<Object> users = sqlSession.selectList("test.selectAll");
        /*----------------------------------------------------------------------------------*/
        System.out.println(users);
        //5、释放资源
        sqlSession.close();
    }
}

改动的配置文件(其他的配置文件和MyBatis快速入门的一样):

image-20220727072918852


image-20220727073204820

使用包扫描简化SQL映射文件的加载:

不使用包扫描加载,需要一个一个将Mapper配置文件进行加载,使用包扫描是直接将一个mapper包加载,一次性就将所有的Mapper配置文件进行了加载,更加简化了代码

image-20220727074415054

加载映射文件的常见方式

<!--MyBatis加载映射文件的常见方式-->
<mappers>
    <!--1、绝对路径法-->
<mapper resource="E:\项目\Project_JavaWeb\day3_mybatis\src\main\resources\com\hhxy\mapper\UserMappper.xml"/>
    <!--2、相对路径法-->
    <mapper resource="com\hhxy\mapper\UserMappper.xml"></mapper>
    <!--3、Mapper代理法:包扫描法-->
    <!--一次加载所有该路径下的SQL映射文件(这里name也可以使用前面的方法)-->
    <package name="com.hhxy.mapper"/>
</mappers>

4、MyBatis核心配置文件详解

详情见这里:MyBatis官方文档

image-20220727203109292

注意核心配置文件的书写顺序要按照上面这个自上而下的顺序,否则会报错,这是xml的约束规范

4.1 properties

既可以在mybatis文件中直接配置,也可以在properties文件中进行配置。

在properties中配置:需要先创建一个properties配置文件,将mybatis核心配置文件中需要替换的信息以键值对的写在里面,最后直接在mybatis核心配置文件中使用properties标签引用就行了。这样做的优点能够实现配置信息和配置文件的解耦,从而提高配置文件的灵活性,每次需要修改配置信息,只需要在properties中改动就行了

  • 在mybatis文件中进行配置:

    image-20220905162149883

  • 在properties文件中进行配置:

    细节:在properties中设置键名时,可以加一个表示功能的前缀,防止键名重复

    注意在properties文件中设置配置信息,一定不要使用转义符,我就是使用了&的转义符&amp;导致报错了!但是在mybatis中设置配置信息时,需要使用转义符

    image-20220905161638680

4.2 settings

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

详情请参考:官方文档

4.3 typeAliases
  • typeAliases:用于给类或包起别名

    1)给类起别名

    在映射配置文件中的 resultType 属性需要配置数据封装的类型(类的全限定名)。而每次这样写是特别麻烦的,Mybatis

    提供了 类型别名 (typeAliases) 可以简化这部分的书写,需要注意它仅用于 XML 配置,意在降低冗余的全限定类名书写。

    <typeAliases> <!--name属性的值是实体类所在包-->
        <package name="com.hhxy.pojo.User"/>
    </typeAliases>
    

    使用typeAliases起别名后,就可以将所有MyBatis配置文件中的 com.hhxy.pojo.类名 替换成 类名(替换后的类名不区分大小写)

    image-20220727213154347

    2)给包起别名

    如果我们的配置文件都是用给类起别名,如果一个包下有很多实体类,要对多个实体类进行起别名,这样就显得很不方便。所以我们可以像之前SQL映射文件的加载一样,我们可以使用包扫描这种思路进行进一步的简化,即:给包起别名

    <typeAliases> <!--name属性的值是实体类所在包-->
        <package name="com.hhxy.pojo"/>
    </typeAliases>
    

    这样com.hhxy.pojo下所有的类都可以直接使用类名(类名同样不区分大小写)

    这里需要注意有一个前提条件,就是:com.hhxy.pojo下的实体类不带有@Alias,如果带有该注解,就以注解值为准

4.4 emvironments
  • environments:用于配置数据库连接的环境信息

    可以配置多个环境变量(environment),用于连接不同的数据库,通过default属性进行切换

    • transactionManager:设置事务管理器

      type:设置事务管理方式,有JDBCMANAGED两种方式。JDBC表示原生的事务管理方式,可手动也可自动;MANAGED:被管理,例如使用Spring时就设置成MANAGED

    • dataSource:设置数据源

      type:设置数据源类型,有POOLEDUNPOOLEDJNDIPOOLED表示使用的数据库连接池缓存数据连接;UNPOOLED表示不使用数据库连接池;JNDI表示使用上下文中的数据源。

    image-20220727205054129

    备注:POOLED是MyBatis默认使用的数据库连接池

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名映射的类型
_bytebyte
_char (since 3.5.10)char
_character (since 3.5.10)char
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
char (since 3.5.10)Character
character (since 3.5.10)Character
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
bigintegerBigInteger
objectObject
date[]Date[]
decimal[]BigDecimal[]
bigdecimal[]BigDecimal[]
biginteger[]BigInteger[]
object[]Object[]
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator
4.4 设置模板

每次我们要写mybati配置文件,都需要去CV,这显得很麻烦,所以我们可以通过设置模板,在IDEA中右击直接创建模板,就可以避免去CV了,进一步简化了开发。模板功能YYDS

image-20220906101426351

image-20220906101632275

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>
<!--
    MyBatis核心配置文件中,标签的顺序:
    properties?,settings?,typeAliases?,typeHandlers?,
    objectFactory?,objectWrapperFactory?,reflectorFactory?,
    plugins?,environments?,databaseIdProvider?,mappers?
-->
    <!--引入properties文件-->
    <!--使用外部引入-->
    <properties resource="jdbc.properties"/>
    <!--设置全局映射-->
    <settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--给实体类所在包起别名,简化书写-->
    <typeAliases>
        <package name="com.hhxy.pojo"/>
    </typeAliases>
    <!--数据库连接环境配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库的连接信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定SQL映射文件-->
    <mappers>
        <!--使用包扫描方式,简化mapper文件的加载-->
        <package name="com.hhxy.mapper"/>
    </mappers>

</configuration>

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">
<!--SQL映射语句-->
<mapper namespace="com.hhxy.mapper.Mapper">
    <!--使用ResultMap标签给字段起别名-->
    <!--
    <resultMap id="brandResultMap" type="User">
        <result column="brand_name" property=""></result>
        <result column="company_name" property=""></result>
    </resultMap>
    -->
    <!--statement语句-->
    
</mapper>

image-20220906224642021

5、使用配置文件进行CRUD

案例代码已经上传到Gitee和GitHub上了😄,欢迎大家参观:

5.1 查询

任务1:查询所有

查询tb_brand表中的所有数据,并且用集合输出查询的所有数据

准备工作:
  • Step1:在数据库中建立tb_brand表

    -- 删除tb_brand表
    drop table if exists tb_brand;
    -- 创建tb_brand表
    create table tb_brand
    (
        -- id 主键
        id           int primary key auto_increment,
        -- 品牌名称
        brand_name   varchar(20),
        -- 企业名称
        company_name varchar(20),
        -- 排序字段
        ordered      int,
        -- 描述信息
        description  varchar(100),
        -- 状态:0:禁用  1:启用
        status       int
    );
    -- 添加数据
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),('小米', '小米科技有限公司', 50, 'are you ok', 1);
    SELECT * FROM tb_brand;
    

    这一步可以尝试着在IDEA中进行,记不得步骤的可以回看进行复习

  • Step2:编写相应的配置文件,同时创建相应的类

    1)需要编写的配置文件有:Maven配置文件、Logback配置文件、MyBatis核心配置文件、SQL映射文件。

    相应配置文件参考MyBatis入门

    2)所需依赖:org.mybatis:mybatis:3.5.5mysql:mysql-connector-java:8.0.27org.slf4j:slf4j-api:1.7.20ch.qos.logback:logback-classic:1.2.3ch.qos.logback:logback-core:1.2.3junit:junit:4.13

    要求

    1. SQL映射文件使用Mapper代理执行SQL语句,并且使用包扫描法进行加载
    2. 对于配置文件中的全类名使用起别名
    3. 使用@Test注解进行测试

    项目目录结构:

    image-20220728174144816

  • Step3:安装MyBatisX插件

    F i l e → S e t t i n g s → P l u g i n s → M a r k e t p l a c e File\rightarrow{Settings}\rightarrow{Plugins}\rightarrow{Marketplace} FileSettingsPluginsMarketplace

    不使用插件,我们在编写Mapper接口的方法时,方法名需要和对应的SQL文件的statement的id值一样,而当我们SQL映射文件中有多个statement时,我们在Mapper接口中写抽象方法时,需要经常跳转到SQL映射文件查看对照,显得很麻烦,而MyBatisX插件就主要是解决这个问题的,让开发变得更加便捷、高效!😃

    MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。

    主要功能:

    1. XML映射配置文件和接口方法间相互跳转

    2. 根据接口方法生成 statement(直接按Alt+Enter

    建议去官网下载,不然可能用了一段时间会报错😆:IDEA官网

    image-20220728170240402

image-20220728170243785

拓展使用Map集合存储查询结果

备注:也可以使用Map集合存储查询结果,一般使用List集合是搭配POJO类,存储的数据是一整条一整条的,字段是固定的,字段名不同需要起别名;而使用Map集合,任何字段都可以(不需要进行字段映射),一般是用来存储查询结果不是实体类

需要注意的是Map集合存储查询结果时,如果查询结果为null,Map集合不会进行存储

  • 方式一:使用List集合存储Map集合

image-20220906115346669

image-20220906115616245

  • 使用MapKey注解:

    image-20220906120214510

    相当于是用一个大的Map集合将所有的返回值的小map集合进行存储

正式开始:
加载MyBatis核心配置文件
获取SqlSessionFactory对象
获取SqlSession对象
执行SQL语句
释放资源
package com.hhxy.test;

import com.hhxy.mapper.BrandMapper;
import com.hhxy.pojo.Brand;
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 MyBatisTest {
    @Test
    public void testSelectAll() throws Exception {
        //1、加载MyBatis核心配置文件,获取SqlSessionFactory对象
        //1.1 确定Mybatis核心配置文件路径
        String resource = "./mybatis-config.xml";
        //1.2 从resources目录下读取MyBatis配置文件,获取InputStream对象
        InputStream is = Resources.getResourceAsStream(resource);
        //1.3 获取SqlSessionFactory对象
        SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(is);

        //2、获取SqlSession对象
        SqlSession sqlS = sqlSF.openSession();

        //3、执行SQL语句(使用Mapper代理)
        //3.1 获取Mapper接口对象
        BrandMapper brandMapper = sqlS.getMapper(BrandMapper.class);
        /*----------------核心代码(其他的代码可以进行CV)-----------------*/
        //3,2 使用Mapper接口对象执行方法
        List<Brand> brands = brandMapper.selectAll();
        /*--------------------------------------------------------------*/
        System.out.println(brands);//打印输出结果,进行检查

        //4、释放资源
        sqlS.close();

    }

}

image-20220728184112439

我们可以发现brandName和companyName都为空,原因是:数据库字段名和实体类的属性名不一致

解决方案

一对一的情况

  1. 对名称不一致的字段起别名,让别名和对应实体类的属性名一致

    image-20220728191707322

    缺点:每次查询都要重新定义一次别名,很繁琐

    可以使用sql片段进一步简化:

    image-20220728192322618

    仍存在缺点:存在硬编码(每次字段起别名都是写死的),不灵活!!!(有点无语😤,直接用第二种方法得了)

    备注:sql片段,一般用来替代*,因为*的使用需要被二次编译,一定程度的降低了SQL的效率,所以不建议使用*好查询所有

  2. 使用resultMap进行自定义映射

    image-20220728195320554

    备注:

    1)resultMap标签中既可以用result标签,也可以用id标签。

    id用来完成主键的映射,result用来完成普通字段的映射

    2)cloum属性的值为数据库字段名,propert属性的值为实体类的属性名。也类似于起别名,但是只需要将数据库字段名和实体类字段名不一样的进行映射就可以了,而不用重复去写名称一样的字段

    3)type的值表示该SQL语句返回值的类型,type="Brand"就表示返回值的类型是com.hhxy.mapper.Brand类型的数据(这里使用了包扫描,所以前面的包名省略了)

  3. 使用settings标签进行全局映射:将数据库中下划线的字段映射成Java中的驼峰样式

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    

    就能直接将所有表中 下划线字段名 映射(相当于起别名)成 驼峰字段名,例如:brand_name映射成brandName

    这个方法最省事(●’◡’●),推荐直接加到mybatis配置文件的模板中

使用这三种方法都能成功解决字段名和属性名不一致的问题:

image-20220728195025576



当遇到多对一(员工表对部门表,多个员工属于同一个部门)时,需要换种方式解决

备注:当一张表有一个外键,则可以通过给对应实体类添加一个引用数据类型来映射外键

多对一的情况

多对于就是多个对象对应一张表,比如员工表对部门表就是多对一,多个员工属于同一个部门

对一需要设置一个对象类型的数据

  1. 原始写法:

image-20220907153140075

  1. 引入外部申明:本质就是使用ResultMap

    PS:这个方式最为简单,推荐使用

    image-20220907154740174

  2. 使用级联:resultMap+association

    image-20220909144653525

    备注:这种方式,需要给表中所有字段与实体类的属性进行映射,否则查询结果会为null,这里age和gender就是,注意:在setting中设置全局的格式转换,也不起作用,仍然需要使用result和id标签进行手动设置,然而在分布查询中如果设置了全局格式转换就不需要在进行手动设置了

  3. 分布查询:也需要使用resultMap+association,同时需要搭配association中的select属性进行SQL关联,属性的返回值类型使用javaType进行设置

    PS:感觉这个方式最为麻烦,不推荐使用

    但是它有一个优点:延迟加载,也称作懒加载

    懒加载:是指只执行需要获取数据的SQL,当关联多个SQL语句,我们所需的结果只需要通过其中一个SQL就能获取了,使用懒加载就只会执行这一个SQL而不会执行其他SQL,从而大大节约资源,MyBatis默认是关闭懒加载的,需要手动打开

    image-20220907172111607

    <settings>
      <!--开启格式转换-->
      <setting name="mapUnderscoreToCamelCase" value="true"/>
      <!--开启懒加载-->
      <setting name="lazyLoadingEnabled" value="true"/>
      <!--完整加载-->
      <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    

    备注:lazyLoadingEnabled设置为trueaggressiveLazyLoading设置为false时,就是按需加载如果aggressiveLazyLoading设置为true时,lazyLoadingEnabled属性会失效

    分布查询步骤:

    1)Step1:直接查询Emp表

    2)Step2:使用ResultMap+association引用另一张表的查询

    image-20220907163738538

    如果在核心配置文件使用setting设置了全局格式转换,就可以将id和result标签的映射去掉了,但是在上一种方式却不行


    image-20220908230633422

    当我们mybatis核心配置文件中的settings标签中进行了全局设置后,如果想要单独设置一个不一样的分布查询SQL,可以使用==fetchType==属性:①eager立即加载(完整加载)②lazy(延迟加载)

    假如我们全局设置了延迟加载,想要单独设置一个关联的SQL进行立即加载,就可以将fetchType属性的值设置为eager

    3)Step3:查询另一张表Dept

    备注:一般而言,不同表的SQL方法写在各表各自对应的Mapper接口中

    image-20220907163954802

    image-20220907164131970

    可以测试,发现同样能成功查询到结果:

    image-20220907171712469

    开启懒加载后,测试结果:

    image-20220907172647327

    aggresssiveLazyLoading属性设置为true时,懒加载失效

    image-20220908230350748

一对多的情况

也就是反过来,部门表对员工表,一个部门有多个员工

对多需要设置一个集合类型的数据

  1. 原始写法:

    image-20220909145959083

  2. 使用resultMap+collection

    image-20220909151819606

    和前面一样,同理也需要手动使用result和id标签对所有字段进行映射,负责查询结果会为null

  3. 分布查询

    直接套模板,注意事项:association中colum属性的值是下一步查询的条件,这和id和result两个标签中的colum属性不一样,这两个标签中的该属性是表示和实体类属性名进行映射的字段名

    同样的和前面一样,也能使用懒加载

    image-20220909160656373

任务2:单条件查询

通过id字段进行查看整行数据

基本上和任务1的代码相同,不同的地方:

SQL映射文件

image-20220728213121620

备注:

  • 所有的statement都推荐使用#{}${}唯一的优点就是用于设置动态表名或字段名,比较灵活(但同样存在SQL注入)

  • 对于比较特殊的SQL,比如:模糊查询、批量删除、动态设置表名,不能直接使用#{},否则会报SQLException

    image-20220906222438332

    解决方案

    • 改为使用${}
    • 使用concat函数:concat('%',#{mohu},'%')
    • 使用双引号:"%"#{mohu}"%"
    • 需要搭配动态SQL

    而批量删除和动态设置表名时,都会因为预编译产生一个被被引号包裹的字符串,而导致SQL异常

    批量删除:in('1,2,3,...');动态设置表名:'tableName',表名不能带引号

  • parameterType属性:

    image-20220728213550644

  • 特殊字符的处理:

    1)使用转义字符,常见转义字符表

    符号对应转义符
    >&gt;
    <&lt;
    &&amp;

    2)使用CDATA区

    备注好像测试出现了一个TypeException异常

Java代码

image-20220728213056700

任务3:多条件查询

多参数传值问题

  1. 使用注解@Param("参数名称")传值。要求==@Param注解的参数名称要和statement中占位符中的参数名称要一致==

    至于为什么要保持一致,可以去看看参数传递这一小节

    image-20220729081433397

  2. 使用对象传值。将多个参数封装成一个实体对象 ,将该实体对象作为接口的方法参数,要求实体对象的属性名要和statement中占位符中的参数名称要一致

    image-20220729085958432

  3. 使用Map集合传值。要求Map集合的键(Key)值要和statment中占位符的参数名称要一致,值(Value)表示用来设置的值

    备注:不按照要求来并不会报错,而是查找可能为空

    image-20220729095429356

相应的测试方法:

    /**
     * 多条件查询
     * @throws Exception
     */
    @Test
    public void testSelectByCondition() throws Exception {
        //模拟用户输入
        int status = 1;
        String companyName = "华为";//公司名
        String brandName = "华为";//品牌名称

        /*使用注解传参数,需要处理参数*/
        companyName = "%"+companyName+"%";
        brandName = "%"+brandName+"%";

        /*使用对象传参数*/
        //不建议使用构造器,因为构造器存在硬编码问题,不够灵活
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);

        /*使用Map集合传参数*/
        Map map = new HashMap();
        map.put("status",status);
        map.put("companyName",companyName);
        map.put("brandName",brandName);


        //1、加载MyBatis核心配置文件,获取SqlSessionFactory对象
        //1.1 确定Mybatis核心配置文件路径
        String resource = "./mybatis-config.xml";
        //1.2 从resources目录下读取MyBatis配置文件,获取InputStream对象
        InputStream is = Resources.getResourceAsStream(resource);
        //1.3 获取SqlSessionFactory对象
        SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(is);

        //2、获取SqlSession对象
        SqlSession sqlS = sqlSF.openSession();

        //3、执行SQL语句(使用Mapper代理)
        //3.1 获取Mapper接口对象
        BrandMapper brandMapper = sqlS.getMapper(BrandMapper.class);
        /*----------------核心代码(其他的代码可以进行CV)-----------------*/
        //3,2 使用Mapper接口对象执行方法

        /*使用注解传参数*/
        //List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);

        /*使用对象传参数*/
        //List<Brand> brands = brandMapper.selectByCondition(brand);

        /*使用Map集合传参数*/
        List<Brand> brands = brandMapper.selectByCondition(map);

        //输出检测
        System.out.println(brands);
        /*--------------------------------------------------------------*/
        //4、释放资源
        sqlS.close();

    }
拓展:动态条件查询

image-20220729104538892

多条件动态查询:

前面的代码仍存在bug

有时候用户只想查询品牌时,只输入一个brandName会导致查不出来结果!这和实际情况相违背,这就需要使用动态SQL进行解决。MyBatis提供了强大的动态SQL!😆真好o(^▽^)o

动态SQL:SQL语句会随着用户的输入和外部条件的变化而变化

多条件动态查询就是,用户会输入多个参数进行查询,但是参数个数并不确定

详细介绍看官网

image-20220729102014878

查询结果

image-20220729101908656

使用上面的动态SQL仍存在bug!(我愿称黑马亮亮老师无敌🐮)

当用户不输入status参数时,由于后面一个If标签有逻辑连接词但前面没有任何表达式,会报错导致查不出数据!

解决方法

  1. 使用恒等式过渡

image-20220729102852546

  1. 使用<where>标签(MyBatis官方觉得前面那种解决方法太low了,就提供了第二种😆,MyBatisYYDS)

    <where>标签的作用:若有条件成立,会自动生成where关键字;若条件成立,且where关键字后面为 “AND” 或 “OR”,会自动将它们去除;若没有条件成立,则不会生成where关键字

image-20220729103546580

拓展trim标签

因为<where>标签只能去除前面的逻辑连接词,当逻辑连接词在表达式的后面时,就无法去除了,这就需要使用trim标签

  • prefix:在标签内容之前添加一些内容
  • prefixOverrides:在标签内容之前去除一些内容
  • suffix:在标签内容之后添加一些内容
  • stuffixOverrides:在标签内容之后去除一些内容

所以我们可以直接使用prefix属性给标签内容前添加一个where关键字,然后使用suffixOverrides属性去除标签内容后的and逻辑链接词。当然trim标签也是可以解决逻辑链接词在前的情况

<select id="getEmpListByMoreTJ" resultType="Emp">
    select * from t_emp
    <trim prefix="where" suffixOverrides="and">
        <if test="empName != '' and empName != null">
            emp_name = #{empName} and
        </if>
        <if test="age != '' and age != null">
            age = #{age} and
        </if>
        <if test="gender != '' and gender != null">
            gender = #{gender}
        </if>
    </trim>
</select>
单条件动态查询:

使用关键字:choose(when,otherwise),类似于switch语句。

单条件动态查询就是,用一个statement语句涵盖所有可能出现的单条件查询,大大减少了代码量的冗余。

image-20220729110745220

备注

  • 一个when标签的条件一旦成立,就不判断后面的条件了

  • 前面的多条件查询statement代码中只需要【将and全部去掉】,然后加一个判断【当所有输入为空时1!=1的条件】,也能变成一个单条件查询

  • 一般都不会使用<otherwise>标签,而是将上面的where换成<where>标签,会自动过滤掉没有条件的where

    如果既不使用<otherwise>标签,又不使用<where>标签,就会报错

    image-20220729112019879

5.2 添加

任务1:添加一条记录

相应的statement

image-20220729143952857

相应测试代码

 	/**
     * 四、添加数据
     * @throws Exception
     */
    @Test
    public void testAdd() throws Exception {
        //模拟用户输入(单条件查询,用户只输入一个参数)
        int status = 1;
        String companyName = "波导手机";//公司名
        String brandName = "波导";//品牌名称
        String description = "手机中的战斗机";
        int ordered = 100;

        /*使用对象传参数*/
        //不建议使用构造器,因为构造器存在硬编码问题,不够灵活
        //id字段一般无需设置,是数据库中的自增字段
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);
        brand.setDescription(description);
        brand.setOrdered(ordered);


        //1、加载MyBatis核心配置文件,获取SqlSessionFactory对象
        //1.1 确定Mybatis核心配置文件路径
        String resource = "./mybatis-config.xml";
        //1.2 从resources目录下读取MyBatis配置文件,获取InputStream对象
        InputStream is = Resources.getResourceAsStream(resource);
        //1.3 获取SqlSessionFactory对象
        SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(is);

        //2、获取SqlSession对象
        SqlSession sqlS = sqlSF.openSession();

        //3、执行SQL语句(使用Mapper代理)
        //3.1 获取Mapper接口对象
        BrandMapper brandMapper = sqlS.getMapper(BrandMapper.class);
        /*----------------核心代码(其他的代码可以进行CV)-----------------*/
        //3,2 使用Mapper接口对象执行方法

        /*使用注解传参数*/
        brandMapper.add(brand);

        /*--------------------------------------------------------------*/
        //4、释放资源
        sqlS.close();

    }

执行成功后会发现,表中并没有添加数据,原因如下:

image-20220729142538123

备注:查询语句不进行事物提交也能查询到结果,事物提交是能够持久影响数据库

方式一

image-20220729142853897

方式二

image-20220729143815871

手动提交后,再次执行可以发现表中的数据已经发生改变了

image-20220729143058469

image-20220729143218138

任务2:批量添加

批量添加需要使用动态SQL中的<forEach>标签,关于该标签的详解可以参考:删除多个、参数传递

  • collection:它的值表示传递的list对象,不使用@Param注解传递参数,collection属性的值可以写:arg0、collection、list

    使用注解传递参数,属性值就使用注解设置的值

  • separator:表示每次遍历后,在标签内容后添加的内容(最后一次遍历不会添加)

    刚好符合SQL批量插入的语法:values(a1,b1,c1,……),values(a2,b2,c2,……),……values(an,bn,cn,……)

image-20220909191909380

注意:非查询SQL记得手动提交事务或者设置自动提交事务

拓展useGeneratedKeyskeyProperty

获取自增的主键

上面的代码仍存在不足之处,即无法直接获取添加数据后的主键id的值!如果想要获取id的值,需要去数据库中进行查找。

解决方法:

image-20220729145022138

  • userGeneratedKeys该属性只能用于insert语句用于判断是否获取数据插入成功后的主键值,默认是false(表示不获取数据插入成功后的主键值)
  • keyProperty:一般是和userGeneratedKeys搭配使用的,用于将获取的主键值绑定到实体类的属性id上,绑定成功后,就能够直接使用get方法获取到id的值

原生JDBC获取自增主键:

    /**
     * 使用原生JDBC实现动态获取自增主键
     */
    @Test
    public void jdbcGenerateKey(){
        try {
            //1、加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2、获取连接对象
            String url = "jdbc:mysql:///ssm?serverTimezone=UTC";
            String user = "root";
            String pwd = "32345678";
            Connection connection = DriverManager.getConnection(url, user, pwd);
            //3、编写SQL
            String username = "lisi";
            String password = "123";
            Integer age = 23;
            String gender = "男";
            String eamil = "123@qq.com";
            String sql = "insert into tb_user values(null,?,?,?,?,?)";
            //4、获取SQL执行对象
            PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

            //给占位符设置值
            ps.setString(1, username);
            // 为sql语句中第二个问号赋值
            ps.setString(2, password);
            // 为sql语句中第三个问号赋值
            ps.setInt(3,age);
            // 为sql语句中第四个问号赋值
            ps.setString(4,gender);
            ps.setString(5,eamil);
            //5、执行SQL
            ps.executeUpdate();
            //获取新增的一行
            ResultSet rs = ps.getGeneratedKeys();
            //让光标指向下一行(也就是新增的一行)
            rs.next();
            int id = rs.getInt(1);
            System.out.println(id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

image-20220907093006105

5.3 修改

任务1:修改所有

更具id一次性修改其他字段的所有数据

相应的statement

image-20220729152500569

相应测试代码

    /**
     * 五、修改
     * @throws Exception
     */
    @Test
    public void testUpdate() throws Exception {
        //模拟用户输入(单条件查询,用户只输入一个参数)
        int status = 1;
        String companyName = "波导手机3";//公司名
        String brandName = "波导3";//品牌名称
        String description = "手机中的战斗机3";
        int ordered = 200;
        int id= 5;

        /*使用对象传参数*/
        Brand brand = new Brand(id,brandName,companyName,ordered,description,status);
        
        //1、加载MyBatis核心配置文件,获取SqlSessionFactory对象
        //1.1 确定Mybatis核心配置文件路径
        String resource = "./mybatis-config.xml";
        //1.2 从resources目录下读取MyBatis配置文件,获取InputStream对象
        InputStream is = Resources.getResourceAsStream(resource);
        //1.3 获取SqlSessionFactory对象
        SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(is);

        //2、获取SqlSession对象
        SqlSession sqlS = sqlSF.openSession(true);//将默认提交方式改成手动

        //3、执行SQL语句(使用Mapper代理)
        //3.1 获取Mapper接口对象
        BrandMapper brandMapper = sqlS.getMapper(BrandMapper.class);
        /*----------------核心代码(其他的代码可以进行CV)-----------------*/
        //3,2 使用Mapper接口对象执行方法
        brandMapper.update(brand);
        /*--------------------------------------------------------------*/
        //4、释放资源
        sqlS.close();
    }
}
任务2:动态修改

动态修改就是,只修改用户输入的多个或一个参数。用户输入什么就修改什么,用户就是上帝~ o( ̄▽ ̄)ブ

注意:动态修改需要使用<set>标签,因为使用set关键字会出现很多问题:

  1. 当最后一条修改语句的参数为空时,会导致前面语句留下导致语法错误
  2. 当修改语句为空,会留下set导致语法错误

image-20220729160755904

相应的statem

image-20220729161255327

5.4 删除

任务1:删除一个

用户输入一个id,通过id删除该行

相应的statement

image-20220729162601330

任务2:删除多个

用户输入多个id,一次性根据多个id删除所在行的数据

传参问题

  1. 直接传数组

image-20220729165405333

底层原理参观后面章节

  1. 使用@Param注解传数组

image-20220729164231010

备注

  • item:表示遍历的每一个id

  • separator:用于设置 遍历后得到的多个id之间的 分隔符

  • open:用于拼接<foreach>标签的左字符

    close:用于拼接<foreach>标签的右字符

    image-20220729164801812

    一个好的程序员往往都会追求代码的最简O(∩_∩)O

拓展:原始写法

image-20220906225501096

解决方法使用${}

但是这个基本上都废除了,还是使用动态SQL标签更香一点😄

6、参数传递

image-20220729195139531

6.1 多个参数

在MyBatis中传递参数时,当抽象方法传递多个参数时,都会生成两个键值对,arg键值对和**Param键值对**

示例:(这里使用前面多条件查询的例子,回看

当我们在进行多个参数传递时,如果注解不和对应statement中占位符的参数名不一致,会直接报错:

image-20220730143051028

直接报错

image-20220729202317621

报错原因:(重点!

在使用MyBatis框架时,当我们在Mapper接口中使用抽象方法一次性传递多个参数时,MyBatis底层会直接将这些参数按照先后顺序,直接封装成Map集合,形成键值对:

Key1arg0:Map集合的键(key),表示第一个参数status传到SQL映射文件中的参数名

Value1param1:Map键arg0对应的值(value),表示第一个参数status的值

Key2arg1:表示第二个参数companyName传到SQL映射文件对应statement中的参数名

Value2param2:表示第二个参数的值

以此类推,每一个arg都有一个对应的param……

重点来了当我们使用@Param注解时,其实就是给param起别名,比如当我们使用这段代码

List<Brand> selectByCondition(int status,
                           @Param("companyName")String companyName, 
                           @Param("brandName")String brandName);

其实就是将param1起个别名叫companyName,将param2起个别名叫brandName。这样做的目的显而易见增强代码的可读性

了解报错原因后,我们就可以知道当我们在不使用注解进行传参数时,可以直接使用:

image-20220729215307328

6.2 单个参数

image-20220730142444720

  • 使用POJO传递参数:直接使用,要求实体类的属性名和对应statement中占位符的参数名称一致
  • 使用Map集合传递参数:直接使用,要求Map集合的键名要和对应statement中占位符的参数名称一致

POJO类型和Map集合类型不仅可以用来传递单个参数,而且还能用来传递多个参数,关于传递多个参数的使用,已经在前面已经讲过了,相信只要懂了怎么使用它们传递多个参数,对于传递单个参数也是一看就懂😄

  • 使用Collection传递参数

    会将参数封装成Map集合,同时生成两个键值对:

    Key1arg0:用来存Collection集合的对象名

    value1param:用来存arg0对应的值

    Key2collection:用来存Collection集合的对象名

    Value2)存key2对应的值

    collectionarg0是等价的,都是用来存Collection集合的对象名

  • 使用List传递参数

    会将参数封装成Map集合,同时生成两个键值对:

    Key1arg0:用来存List集合的对象名

    Value1param:用来存arg0对应的值

    Key2collection:用来存List集合的对象名

    Value2)存Key2相应的值

    Key3list:用来存List集合的对象名

    Value3)存Key3相应的值

  • 使用Array传递参数

    会将参数封装成Map集合,同时生成两个键值对:

    Key1arg0:用来存Arrray集合的对象名

    Value1param:用来存arg0对应的值

    Key2array:用来存Array集合的对象名

    Value2)存Key2相应的值

关于参数传递的总结

  • 在使用MyBatis进项目开发时,遇到以下两种情况,强烈建议使用@Param注解给参数起别名(提高代码可读性)

    ①在传多个参数时,直接传递,可以使用Map集合、注解

    ②传单个参数使用CollectionListArray这三种方式进行传递

  • 除了POJO方式以外,其他参数的传递都是使用Map集合进行的

  • 能用来传递多个参数的方式也同样能用来传递单个参数

说了这么多来点实际的🐵,上道面试题🗡 :

image-20220730155201536

正确答案

  • 第一个占位符中的参数填:user.username
  • 第二个占位符中的参数填:user.password

填其他答案,查询结果都为空或者直接报错~

答案解析

image-20220730171648650

两个条件叠加起来,就是答案了。至于为什么是键名.属性名这种写法,暂时还未想到原因,我认为可能这就是一种规范吧,类似于为什么引用对象中的方法,需要对象名.方法名

查询结果

image-20220730171926586

7、使用注解进行CRUD

使用注解比使用配置文件更加简便,主要体现:使用注解无需使用配置文件去实现Mapper接口中的抽象方法。

注意:使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句

image-20220730180629658

测试

image-20220730205038957

结果:

image-20220730204902440

其他的SQL语句也是一样的,其实就是通过注解将写在配置文件中的SQL语句移到了Mapper接口中了


总结

写在最后的话

  想起两天前我还不知道MyBatis是啥,还对它有一点恐惧😱和担心😨,人可能就是这样的,总是对未知的事物产生恐惧,现在学完这一章节虽说还谈不上能熟练使用,但对MyBatis还有一个大致的了解了O(∩_∩)O

2
  • 本文若对你有一定的帮助,欢迎小伙伴们的点赞👍、评论✍、收藏⭐
  • 一起加油💪,让我们一步步走向聪明绝顶的道路吧😆

本章思维导图(方便快速回忆,定位知识点):

image-20220731111340553


推荐阅读

  • 【JavaWeb系列】上一篇文章:一文教你快速上手Maven
  • 对JDBC学习的回顾:JDBC学习路线总结

  1. 持久层也称数据访问层(Data Access Layer)。其功能主要是负责数据库的访问。简单地说就是实现对数据表的Select(查询)、Insert(插入)、Update(更新)、Delete(删除)等操作,即:将数据保存到数据库的那一层代码。 ↩︎

  2. 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。 ↩︎

  3. 解耦就是解除两者之间的关联,从而让代码能够随时更换SQL语句 ↩︎

  4. POJO类就是实体类,一般用来接收来自文件、数据库的数据 ↩︎

  5. 硬编码,就是将整个SQL语句当作参数直接传进方法中。硬编码不利于代码后续的更新和维护 ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知识汲取者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值