Mybatis快速入门与核心知识总结

发布于:2025-02-11 ⋅ 阅读:(11) ⋅ 点赞:(0)


MyBatis 是一个优秀的持久层框架,它简化了 JDBC 的使用,允许开发者通过 XML 或注解方式配置 SQL 语句,并自动将查询结果映射为 Java 对象,从而高效地进行数据库操作。

1. 实体类(Entity Class)

com/itheima/pojo/User.java

package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Integer age;
}

1.1 实体类的定义

实体类(Entity Class)是用于表示数据库中数据结构的对象模型。它们通常包含与数据库表列相对应的属性,并提供相应的getter和setter方法来访问这些属性。此外,实体类还可能包含一些业务逻辑或验证规则。

在这里插入图片描述

1.2 简化编写

其中,@Data@AllArgsConstructor@NoArgsConstructor 是 Lombok 提供的注解,用于简化 Java 类的编写。这些注解可以自动生成常见的代码,减少样板代码(boilerplate code),使代码更加简洁和易读。下面是对这三个注解的简要解释:

1.2.1 @Data

@Data 是 Lombok 提供的一个综合性注解,它实际上是以下多个注解的组合:

  • @Getter@Setter: 自动生成所有字段的 getter 和 setter 方法。
  • @ToString: 自动生成 toString() 方法。
  • @EqualsAndHashCode: 自动生成 equals()hashCode() 方法。
  • @RequiredArgsConstructor: 生成一个包含所有 final 字段或标记为 @NonNull 的构造函数。

1.2.2 @AllArgsConstructor

@AllArgsConstructor 注解用于生成一个包含所有字段的构造函数。每个字段都会成为构造函数的一个参数。

使用 @AllArgsConstructor 注解后,Lombok 会为 User 类生成如下构造函数:

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

1.2.3 @NoArgsConstructor

@NoArgsConstructor 注解用于生成一个无参构造函数。这对于需要反射创建对象的框架(如 Spring、Hibernate 等)非常有用。

使用 @NoArgsConstructor 注解后,Lombok 会为 User 类生成如下无参构造函数:

public User() {
}

2. 创建 Mapper 接口

创建一个 UserMapper 接口,定义与 User 相关的数据库操作方法。
com/itheima/mapper/UserMapper.java

package com.itheima.mapper;

import com.itheima.pojo.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper //应用程序在运行时, 会自动的为该接口创建一个实现类对象(代理对象), 并且会自动将该实现类对象存入IOC容器 - bean
public interface UserMapper {

    /**
     * 查询所有用户
     */
    @Select("select id, username, password, name, age from user")
    public List<User> findAll();

    /**
     * 根据ID删除用户
     */
    @Delete("delete from user where id = #{id}")
    //public void deleteById(Integer id);
    public Integer deleteById(Integer id);

    /**
     * 新增用户
     */
    @Insert("insert into user(username, password, name, age) values (#{username}, #{password}, #{name}, #{age})")
    public void insert(User user);

    /**
     * 更新用户
     */
    @Update("update user set username = #{username}, password = #{password}, name = #{name}, age = #{age} where id = #{id}")
    public void update(User user);

    /**
     * 根据用户名和密码查询用户
     */
    @Select("select * from user where username = #{username} and password = #{password}")
    public User findByUsernameAndPassword(@Param("username") String username,@Param("password")  String password);
}

2.1 @Param

@Param 注解用于给方法参数命名,使得在 SQL 映射文件或注解中可以通过名称引用这些参数。这对于有多个参数的方法特别有用,而且在默认情况下,方法的形参名称不会被保留在 .class 字节码中。这意味着在运行时,MyBatis 无法直接获取方法参数的名称,只能通过参数的顺序进行绑定。

  • 可读性:通过命名参数,SQL 语句更易于理解和维护。
  • 灵活性:允许在同一个方法中有多个参数,并且每个参数都可以通过名称引用,而不是依赖于位置。
  • 避免混淆:当有多个参数时,避免因参数顺序错误导致的问题。

然而,若您基于 Spring Boot 框架进行开发,并且您的项目继承自 spring-boot-starter-parent 父级工程,则该父级工程已预配置了以下插件。这使得在编译后能够保留方法的形式参数名称,从而允许框架在运行时访问这些参数名称。

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

2.2 #{} 占位符

#{} 是 MyBatis 中用于传递参数的占位符。它会将传入的参数值进行预编译处理,防止 SQL 注入攻击,并提高查询效率,以下是占位符与拼接符的区别

特性 #{} 占位符 ${} 拼接符
预编译 支持,防止 SQL 注入 不支持,容易导致 SQL 注入
类型转换 自动进行类型转换 不进行类型转换
适用场景 绑定参数值,如字段值、条件等 动态生成 SQL 语句,如表名、列名等
安全性 高,防止 SQL 注入 低,容易受到 SQL 注入攻击
性能 高,可以利用数据库的执行计划缓存 低,每次执行都需要重新解析和编译
灵活性 较低,适合固定结构的 SQL 语句 高,适合动态生成 SQL 语句
  • #{} 占位符:用于传递参数值,支持预编译和类型转换,防止 SQL 注入,适合大多数场景。
  • ${} 拼接符:用于直接拼接 SQL 字符串,不进行预编译和转义处理,适合动态生成 SQL 语句,但需特别注意安全性。

2.3 SQL 预编译

SQL 预编译(Prepared Statements)是指在执行 SQL 语句之前,先将其编译成数据库可以识别的执行计划,然后在实际执行时只需要传递参数即可。这种方式不仅可以提高查询效率,还能有效防止 SQL 注入攻击。

  • 安全性:通过预编译机制,参数会被安全地传递到数据库,避免了直接拼接 SQL 字符串带来的 SQL 注入风险。
  • 性能提升:对于重复执行的 SQL 语句,数据库可以缓存并重用执行计划,减少解析和编译的时间开销。
  • 简化开发:开发者无需手动编写复杂的 SQL 语句拼接逻辑,减少了出错的可能性。

3. 配置 MyBatis XML 映射文件(可选)

使用 MyBatis 的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的 SQL 功能,建议使用 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">

<mapper namespace="com.itheima.mapper.UserMapper">

    <!-- 根据ID删除用户 -->
    <select id="deleteById" parameterType="int" resultType="com.itheima.pojo.User">
        SELECT * FROM User WHERE id = #{id}
    </select>

    <!-- 查询所有用户 -->
    <select id="findAll" resultType="com.itheima.pojo.User">
        SELECT * FROM User
    </select>

3.1 默认规则

  • XML 映射文件的名称与 Mapper 接口名称一致,并且将 XML 映射文件和 Mapper 接口放置在相同包下(同包同名)。
  • XML 映射文件的 namespace 属性为 Mapper 接口全限定名一致。
  • XML 映射文件中 sql 语句的 id 与 Mapper 接口中的方法名一致,并保持返回类型一致。

在这里插入图片描述

4. 配置 MyBatis 主配置文件

application.properties

spring.application.name=springboot-mybatis-quickstart
spring.datasource.url=jdbc:mysql://localhost:3306/userdb
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=mq20011103
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

这段配置文件是典型的 Spring Boot 应用程序中的 application.propertiesapplication.yml 文件的一部分,用于配置应用程序的名称、数据源连接信息以及 MyBatis 的日志实现。下面是对每个配置项的详细解析:

4.1 Properties配置项解析

  • spring.application.name=springboot-mybatis-quickstart

  • 作用:设置应用程序的名称。

  • 解释:这个属性定义了应用的名称,通常用于在日志、监控工具和其他地方标识该应用。在这个例子中,应用的名称为 springboot-mybatis-quickstart

  • spring.datasource.url=jdbc:mysql://localhost:3306/userdb

  • 作用:设置数据库连接的 URL。

  • 解释:这个属性指定了要连接的数据库的 JDBC URL。这里的 URL 表示连接到本地 (localhost) MySQL 数据库服务器上的 userdb 数据库,端口号为 3306。

  • spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

  • 作用:设置数据库驱动类名。

  • 解释:这个属性指定了用于连接数据库的 JDBC 驱动类。对于 MySQL 数据库,驱动类名为 com.mysql.cj.jdbc.Driver,这是 MySQL Connector/J 提供的驱动类。

  • spring.datasource.username=root

  • 作用:设置数据库用户名。

  • 解释:这个属性指定了连接数据库时使用的用户名。在这个例子中,用户名为 root

  • spring.datasource.password=mq20011103

  • 作用:设置数据库密码。

  • 解释:这个属性指定了连接数据库时使用的密码。在这个例子中,密码为 mq20011103。请注意,实际生产环境中应确保密码的安全性,避免直接硬编码在配置文件中。

  • mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

  • 作用:设置 MyBatis 的日志实现类。

  • 解释:这个属性指定了 MyBatis 使用的日志实现类。org.apache.ibatis.logging.stdout.StdOutImpl 表示将 MyBatis 的日志输出到标准输出(控制台)。这有助于调试和查看 SQL 执行情况。

4.2 Properties 和 YAML/YML 配置文件的对比

特性 Properties 文件 YAML 文件
语法 扁平化键值对 层次结构化,使用缩进
可读性 较低,尤其是复杂配置 高,结构清晰
维护性 较低,特别是对于嵌套配置 高,嵌套结构易于管理
数据类型支持 仅支持字符串,需手动转换其他类型 支持多种数据类型,自动类型转换
缩进敏感性 不敏感 敏感,必须保持一致的缩进
使用场景 简单配置,传统应用 复杂配置,现代框架如 Spring Boot

application.yaml/yml

spring:
  application:
    name: springboot-mybatis-quickstart
  datasource:
    url: jdbc:mysql://localhost:3306/userdb
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: mq20011103

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

5. 编写测试代码

编写一个简单的测试类来验证这些操作是否正常工作:

package com.itheima;

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

import java.util.List;

@SpringBootTest
class AliyunMybatisQuickstartApplicationTests {


    @Autowired
    private UserMapper userMapper;

    @Test
    public void testFindAll(){
        List<User> userList = userMapper.findAll();
        userList.forEach(System.out::println);
    }

    /**
     * 测试删除
     */
    @Test
    public void testDeleteById(){
        Integer i = userMapper.deleteById(4);
        System.out.println("执行完毕, 影响的记录数: " + i);
    }

    /**
     * 测试新增
     */
    @Test
    public void testInsert(){
        User user = new User(null,"gaoyuanyuan","666888","高圆圆", 18);
        userMapper.insert(user);
    }

    /**
     * 测试更新
     */
    @Test
    public void testUpdate(){
        User user = new User(1,"zhouyu","666888","周瑜", 20);
        userMapper.update(user);
    }

    /**
     * 测试查询
     */
    @Test
    public void testSelect(){
        User user = userMapper.findByUsernameAndPassword("zhouyu", "666888");
        System.out.println(user);
    }

}

5.1 @SpringBootTest

@SpringBootTest 是一个用于集成测试的注解,它会启动整个 Spring Boot 应用程序上下文(ApplicationContext),以便在测试环境中进行依赖注入和其他 Spring 功能的测试。

  • 启动整个应用程序:当使用 @SpringBootTest 注解时,Spring Boot 会自动创建并启动一个完整的应用程序上下文,类似于实际运行的应用程序。
  • 自动配置:该注解会自动加载应用程序的配置文件(如 application.propertiesapplication.yml),并根据这些配置初始化相应的 Bean。
  • 依赖注入:允许在测试类中使用 @Autowired 注解来注入需要测试的组件或服务。

5.2 @Autowired

@Autowired 是一个用于依赖注入的注解,它可以自动将所需的依赖项注入到类中。

  • 自动注入:通过 @Autowired 注解,Spring 容器会自动查找匹配的 Bean 并将其注入到目标字段、构造函数或方法参数中。
  • 字段注入:可以直接在字段上使用 @Autowired,如示例中的 userMapper 字段。
  • 构造函数注入:也可以在构造函数上使用 @Autowired,这种方式通常被认为更安全和推荐。
  • Setter 方法注入:可以在 setter 方法上使用 @Autowired,但这种方式较少使用。

5.3 userList.forEach(System.out::println)

userList.forEach(System.out::println); 这行代码使用了 Java 8 引入的 方法引用Lambda 表达式,目的是对 userList 中的每一个元素调用 System.out.println() 方法进行打印。

  • 等效的 Lambda 表达式 如果你不使用方法引用,可以使用 Lambda 表达式来实现相同的功能:
    userList.forEach(user -> System.out.println(user));