MyBatis 入门

目录

[一. MyBatis 概述](#一. MyBatis 概述)

[二. MyBatis 入门](#二. MyBatis 入门)

[1. 创建工程, 导入依赖](#1. 创建工程, 导入依赖)

[2. 数据准备](#2. 数据准备)

[3. 配置数据库相关信息](#3. 配置数据库相关信息)

[4. 编写持久层代码](#4. 编写持久层代码)

[5. 编写测试代码](#5. 编写测试代码)

[三. MyBatis基础操作.](#三. MyBatis基础操作.)

[1. 打印日志](#1. 打印日志)

[2. 参数传递](#2. 参数传递)

[3. 增 (Insert)](#3. 增 (Insert))

[4. 删 (Delete)](#4. 删 (Delete))

[5. 改 (Update)](#5. 改 (Update))

[6. 查 (Select)](#6. 查 (Select))

[(1) 起别名](#(1) 起别名)

[(2) 结果映射](#(2) 结果映射)

[(3) 开启驼峰命名与蛇形命名转换](#(3) 开启驼峰命名与蛇形命名转换)

[四. MyBatis XML配置文件](#四. MyBatis XML配置文件)

[(1) 配置连接字符串和MyBatis](#(1) 配置连接字符串和MyBatis)

[(2) 编写持久层代码](#(2) 编写持久层代码)

[① 添加Mapper接口](#① 添加Mapper接口)

[② 添加UserInfoXMLMapper.xml](#② 添加UserInfoXMLMapper.xml)

[③ 单元测试](#③ 单元测试)

[(3) 增删改查操作](#(3) 增删改查操作)

[① 增 (Insert)](#① 增 (Insert))

[② 删 (Delete)](#② 删 (Delete))

[③ 改 (Update)](#③ 改 (Update))

[④ 查 (Select)](#④ 查 (Select))


一. MyBatis 概述

前面我们学习过使用JDBC编程对数据库进行操作. 不过JDBC对于数据库的操作过于麻烦, 所以我们在Spring中引入MyBatis框架, 来帮助我们对数据库进行操作.

MyBatis 是一款优秀的持久层框架, 用于简化JDBC的开发.

持久层(Mapper/Dao), 就是用来操作数据库的.

简单来说, MyBatis 是一个能够更简单地完成程序和数据库交互的框架. 接下来,我们就通过一个入门程序,让大家感受一下通过Mybatis如何操作数据

二. MyBatis 入门

1. 创建工程, 导入依赖

MyBatis 是一个持久层框架, 具体的数据存储和数据操作还是在MySQL中进行的. 所以我们还需要添加MySQL驱动.

项目工程创建完成后, 我们就会发现: 在pom.xml文件中, 自动导入了Mybatis依赖和MySQL驱动依赖.

2. 数据准备

创建用户表:

sql 复制代码
-- 创建数据库 
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据 
USE mybatis_test;
-- 创建表[用户表] 
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
 `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
 `username` VARCHAR ( 127 ) NOT NULL,
 `password` VARCHAR ( 127 ) NOT NULL,
 `age` TINYINT ( 4 ) NOT NULL,
 `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
 `phone` VARCHAR ( 15 ) DEFAULT NULL,
 `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
 `create_time` DATETIME DEFAULT now(),
 `update_time` DATETIME DEFAULT now(),
 PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 
-- 添加用户信息 
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

创建对应的实体类 UserInfo: (其中实体类的属性名 和表中的字段名 一一对应)

java 复制代码
package com.jrj.mybatis;

import lombok.Data;
import java.util.Date;

@Data
public class UserInfo{
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

3. 配置数据库相关信息

MyBatis中 要连接数据库 需要配置数据库的相关参数, 包括数据库URL, 用户名, 密码, MySQL驱动类. 这些配置信息均在配置文件中完成.

java 复制代码
# 数据库连接配置 
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
	username: root
	password: root
	driver-class-name: com.mysql.cj.jdbc.Driver

如上代码, mybatis_test 就是数据库的名称.

注意\]: 如果password是纯数字的话, 需要在数字的的外围用单引号括起来. ### 4. 编写持久层代码 ```java package com.jrj.mybatis.mapper; import com.jrj.mybatis.UserInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface UserInfoMapper { @Select("select * from userinfo") public List selectAllUser(); } ``` > **@Mapper 注解: 表示MyBatis中的Mapper接口.** > > **@Select 注解: 表示Select查询 (代表注解中方法的具体实现)** \[注意\]: **像上述代码这样返回多条数据的接口, 一定要用List来接收数据; MyBatis的持久层接口一般都叫 "xxxMapper".** ### 5. 编写测试代码 自动生成: 在想要测试的接口中点击右键, 点击生成, 选择想要测试的方法, 即可生成测试代码. ## **三. MyBatis基础操作.** ### 1. 打印日志 在Mybatis当中, 我们可以借助日志, 查看到sql语句的执行, 执行传递的参数以及执行结果. 在配置文件中进行配置即可. ```java mybatis: configuration: # 配置打印 MyBatis⽇志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` 配置好之后, 重新运行程序, 即可看到SQL的执行内容. ### 2. 参数传递 如果我们现在需要查找 id=4 的用户, 对应的 sql语句 就是 select \* from userinfo where id=4. ```java @Select("select * form userinfo where id = 4") public UserInfo selectUser(); ``` 但是这样的话, 就只能查询到 id为4 用户的数据. 所以我们**不建议把sql语句写死** . 我们需要把 id 变为动态的数值. 解决办法就是在selectUser方法中添加一个参数(id), **将方法中的参数传递给sql语句** .使用**#{}**的方式在sql语句中获取方法中传递的参数. ```java @Select("select * from userinfo where id = #{id}") public UserInfo selectUser(Integer id); ``` ```java void selectUser() { System.out.println(userInfoMapper.selectUser(4)); } ``` > \[注意\]: > > * 如果**参数只有一个**, #{ } 内的属性名称可以随便写. > * 如果**参数有多个** , 属性名和**参数名必须保持一致**; 或**按照顺序对应**(param1, param2...). ① 按名称对应 ```java @Select("select * from userinfo where username = #{name} and id = #{id}") public UserInfo selectUser2(String name,Integer id); ``` ```java @Test void selectUser2() { System.out.println(userInfoMapper.selectUser2("admin",1)); } ``` ② 按顺序对应 ```java @Select("select * from userinfo where username = #{param1} and id = #{param2}") public UserInfo selectUser3(String name,Integer id); ``` ```java @Test void selectUser3() { System.out.println(userInfoMapper.selectUser3("admin",1)); } ``` \[注\]: 也可以通过@Param注解, 设置参数的别名. 如果使用@Param设置别名, **注解中的别名必须和sql中的属性名保持一致.**举例如下: ```java @Select("select * from userinfo where id = #{ID}") public UserInfo selectUser4(@Param("ID") Integer id); ``` ```java @Test void selectUser4() { System.out.println(userInfoMapper.selectUser4(1)); } ``` ### 3. 增 (Insert) sql语句: > **insert into userinfo (username, \`password\`, age, gender, phone) values ("zhaoliu","zhaoliu",19,1,"15585133024")** 把SQL中的常量换为动态的参数. Mapper接口: ```java @Insert("insert into userinfo (id,username,password,age,gender,phone) values (" + "#{id},#{username},#{password},#{age},#{gender},#{phone})") public Integer insertUser1(UserInfo userInfo); ``` 这里我们可以直接使用UserInfo对象的属性来获取参数: ```java @Test void insertUser1() { UserInfo userInfo = new UserInfo(); userInfo.setId(5); userInfo.setUsername("zhaoliu"); userInfo.setPassword("zhaoliu"); userInfo.setAge(19); userInfo.setGender(1); userInfo.setPhone("15585133024"); userInfoMapper.insertUser1(userInfo); } ``` 如果设置了 **@Param** 属性, #{...} 需要使用 **参数. 属性** 来获取. 返回主键 Insert语句默认返回的是受影响的行数. 但是有些情况下, 数据插入之后, 还需要有后续的关联操作, 需要获取到新插入的数据的id. 如果想要拿到自增id, 需要在Mapper接口的方法上添加一个Options的注解. ```java @Options(useGeneratedKeys = true,keyProperty = "id") @Insert("insert into userinfo (id,username,password,age,gender,phone) values (" + "#{id},#{username},#{password},#{age},#{gender},#{phone})") public Integer insertUser2(UserInfo userInfo); ``` ### 4. 删 (Delete) sql语句: > **delete from userinfo where id=6** 把sql语句中的常量替换为动态参数. Mapper接口: ```java @Delete("delete from userinfo where id = #{id}") public Integer deleteUser1(Integer id); ``` ```java @Test void deleteUser1() { System.out.println(userInfoMapper.deleteUser1(6)); } ``` ### 5. 改 (Update) sql语句: > **update userinfo set username="zhaoliu" where id=5** 把SQL中的常量替换为动态的参数 Mapper接口: ```java @Update("update userinfo set username = #{username} where id = #{id}") public Integer updateUser(UserInfo userInfo); ``` ```java @Test void updateUser() { UserInfo userInfo = new UserInfo(); userInfo.setId(5); userInfo.setUsername("tianqi"); System.out.println(userInfoMapper.updateUser(userInfo)); } ``` ### 6. 查 (Select) **只有Java对象属性和数据库字段⼀模⼀样时,才会进行赋值**. 当自动映射查询结果的时候, MyBatis会获取结果中返回的列名并在Java类中查找相同名字的属性(忽略大小写). 这意味着如果发现了ID列和id属性, MyBatis会将 ID列的值 赋给 id属性. 但是我们的创建时间, 更新时间, 删除逻辑数字: 在数据库中是蛇形结构的名字, 而在Java类中是小驼峰的格式. ![](https://i-blog.csdnimg.cn/direct/d48d4ddd732c4e389b96765248f56730.png) 问题如上图, 那如何解决这个问题呢? #### (1) 起别名 在sql语句中, 给列名起别名, 保持 **别名** 和 **实体类属性名**一致. ```java @Select("select id, username, `password`, age, gender, phone, " + "delete_flag as deleteFlag," + "create_time as createTime, update_time as updateTime from userinfo") public List selectAllUser2(); ``` \[注\]: 当sql语句太长的时候,我们可以使用 + 进行拼接. #### (2) 结果映射 ```java @Results({ @Result(column = "delete_flag",property = "deleteFlag"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time",property = "updateTime") }) @Select("select * from userinfo") public List selectAllUser3(); ``` * @Results 注解 中可以**用大括号括起多个@Result映射.** * @Result**前面的参数** 是表的**字段名** , **后面是Java类的属性** . (**字段与属性一一映射**) 如果其他sql也想**复用** 这一组映射, 可以给这一组 @Results映射 **自定义一个名称** . 之后在想要复用这个sql映射的地方使用 **@ResultMap**(vlaue="映射名称") 来实现映射的复用. ```java @Results(id = "resultMap1",value = { @Result(column = "delete_flag",property = "deleteFlag"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time",property = "updateTime") }) @Select("select * from userinfo") public List selectAllUser3(); @ResultMap(value = "resultMap1") @Select("select * from userinfo where id = #{id}") public UserInfo selectUser5(Integer id); ``` @ResultMap注解 中的 value 的值和上面映射的 id 名字必须相同. 我们也可以在xml文件中使用 \ 和 \ 标签来完成. ```XML ``` 指定好结果映射之后, 就可以在对应的sql标签之后**使用 resultMap 来指定结果映射.** ```XML ``` 我们也可以使用 extends 来继承结果映射, 在继承过来的结果映射中添加还未存在的字段. ```XML ``` #### (3) 开启驼峰命名与蛇形命名转换 通常++数据库列使用蛇形命名法进行命名(下划线分割各个单词), 而Java属性⼀般遵循驼峰命名法约定.++ 为了**在这两种命名方式之间启用自动映射** , 需要 **将mapUnderscoreToCamelCase设置为true .**我们需要在配置文件中配置. ```XML mybatis: configuration: map-underscore-to-camel-case: true #配置驼峰⾃动转换 ``` 转换规则: abc_xyz --\> abcXyz (蛇形转换为小驼峰). 而Java代码不用做任何处理: ```java @Select("select * from userinfo") public List selectAllUser(); ``` ## 四. MyBatis XML配置文件 MyBatis 的开发方式有两种: > **1. 注解** > > **2. XML** 使用Mybatis的注解方式, 主要是来完成一些简单的增删改查功能. 如果需要实现复杂的SQL功能, 建议使用XML来配置映射语句 (也就是将SQL语句写在XML配置文件中). 前面我们学习了注解方式, 下面我们来看XML方式: 这种开发方式大致分为两步: > (1) 配置 **数据库连接字符串** 和 **MyBatis**. > > (2) 编写**持久层代码** ### (1) 配置连接字符串和MyBatis ```XML # 数据库连接配置 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mybatis_test? characterEncoding=utf8&useSSL=false username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件 mybatis: mapper-locations: classpath:mapper/**Mapper.xml ``` mapper-locations 中的value值, classpath表示的是项目中的resource目录. mapper表示的是一个自定义目录. 一般我们使用xml操作数据库的代码都会单独放在一个mapper目录中, 之后\*\*Mapper.xml表示的是以这个结尾的xml文件就是操作数据库的xml文件. ### (2) 编写持久层代码 持久层代码分为两部分: > **① 方法定义: Interface > ② 方法实现: xxx.xml** ![](https://i-blog.csdnimg.cn/direct/d04b248a292e4dc1840a92456786ff90.png) #### ① 添加Mapper接口 ```java package com.jrj.mybatis.mapper; import com.jrj.mybatis.UserInfo; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserInfoXMLMapper { public List selectAllUser1(); } ``` #### ② 添加UserInfoXMLMapper.xml ```java ``` **mapper标签** 中加的是**带有@Mapper注解接口的路径**, 即想要通过MyBatis操作数据库的Mapper接口. 查询所有用户的具体实现: ```java ``` * 其中. select标签中 id="selectAllUser1" 代表的是Mapper中的方法名; resultType="com.jrj.mybatis.UserInfo" 代表的是sql查询之后返回的类型 (也就是我们开头定义的实体类) * 只有select类型的语句会有返回值的类型. \[注意\]: 是sql查询之后返回的类型, 不是接口返回值的类型. (sql查询之后返回的是UserInfo类型, 而接口返回的是List类型.) * 标签中间写的是sql语句. 我们还可以安装一个插件, 叫做MyBatisX, 这个插件可以自动帮助我们生成xml标签. 我们只需要写sql语句就行了. #### ③ 单元测试 进行单元测试时, 我们可以在Mapper上点击右键 --\> 生成 --\> 测试 --\> 勾选想要测试的方法, 就会在test目录下**自动生成测试类和测试方法** , 其中**测试方法的返回值必须为void**. ```java @Test void selectAllUser1() { List list = userInfoXMLMapper.selectAllUser1(); for (UserInfo userInfo: list){ System.out.println(userInfo); } } ``` ### (3) 增删改查操作 #### ① 增 (Insert) UserInfoMapper接口: ```java public Integer insertUser(UserInfo userInfo); ``` XML: ```java insert into userinfo (id,username,password,age,gender,phone) values (#{id},#{username},#{password},#{age},#{gender},#{phone}) ``` 测试代码: ```java @Test void insertUser() { UserInfo userInfo = new UserInfo(); userInfo.setId(8); userInfo.setUsername("zhubajie"); userInfo.setAge(22); userInfo.setPassword("6666666"); userInfo.setGender(0); userInfo.setPhone("487362849326"); userInfoXMLMapper.insertUser(userInfo); } ``` 与注解实现类似,要是在形参的前面加上 @Param注解 的话,在sql语句中的 #{ } 就必须使用**对象名.属性名** 来访问. Mapper接口: ```java public Integer insertUser(@Param("userinfo") UserInfo userInfo); ``` XML: ```java insert into userinfo (id,username,password,age,gender,phone) values (#{userinfo.id},#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender},#{userinfo.phone}) ``` #### ② 删 (Delete) #### ③ 改 (Update) #### ④ 查 (Select) 删, 改, 查和增是同样的道理, 我们不再赘述.

相关推荐
果冻kk10 分钟前
【宇宙回响】从Canvas到MySQL:飞机大战的全栈交响曲【附演示视频与源码】
java·前端·数据库·spring boot·mysql·音视频·html5
Achou.Wang26 分钟前
go语言中空结构体
开发语言·后端·golang
Asthenia041227 分钟前
从源码看 MyBatis-Plus 与 Spring 的 DataSourceTransactionManager 有没有直接关联?
后端
程序媛小盐31 分钟前
Java基础编程练习第34题-正则表达式
java·开发语言·正则表达式
炬火初现32 分钟前
Go语言的基础类型
开发语言·后端·golang
极客先躯33 分钟前
高级java每日一道面试题-2025年3月06日-微服务篇[Eureka篇]-Eureka服务注册与发现是什么?
java·微服务·eureka
少年的范儿36 分钟前
maven在windows系统上的详细安装和配置
java·windows·maven
卑微小文38 分钟前
国内金融资讯平台信息聚合:代理 IP 打破信息孤岛
后端
不如打代码KK40 分钟前
jvm中每个类的Class对象是唯一的吗
java·jvm