Spring Boot整合MyBatis(保姆级教程)

news2024/11/14 10:32:37

前言

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

本文通过 Spring Boot + MyBatis 实现一个用户管理的例子,来带大家入门 MyBatis。本教程适合小白入手,文中如有差错还请各位不吝赐教,大家一起学习,共同进步。

配置数据库

数据库采用的是 MySQL,首先提前安装好 MySQL 数据库。

创建数据库

数据库安装完毕后,在命令行中登录 MySQL

$ mysql -u root -p

创建名字叫 mybatisdemo 的数据库:

$ create database mybatisdemo

进入 mybatisdemo 数据库:

$ use mybatisdemo

创建 user 表:

CREATE TABLE `user`
(
    `id` int(10) NOT NULL AUTO_INCREMENT,
    `user_name` varchar(30) NOT NULL,
    `password` varchar(50) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;

user 表包含三个字段:iduser_namepassword,其中 id 是主键并且是自增的。

查看 user 表:

$ desc user;

结果如下:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int          | NO   | PRI | NULL    | auto_increment |
| user_name | varchar(30)  | NO   | UNI | NULL    |                |
| password  | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

创建 Spring Boot 工程

VSCode 创建 Spring Boot 工程

使用 VSCode 创建一个 Spring Boot 工程。通过 command + shift + p 快捷方式快速创建一个 Spring Boot 项目。

选择创建一个 java 项目:

image.png

选择项目类型为 Spring Boot

image.png

选择创建一个 Maven 工程:

image.png

选择 Spring Boot 版本号:

image.png

选择工程的编程语言:

image.png

选择 Group Id,这里我填写 com.sac:

image.png

填写工程的 Artifact Id,这里我填写 demo:

image.png

选择打包类型:

image.png

选择 java 版本号:

image.png

选择需要安装的依赖包,这里暂时先跳过去:

image.png

到这里就成功初始化一个 Spring Boot 工程了,目录结构如下:

image.png

引入依赖

修改工程根目录下的 pom.xml 文件,引入相关依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--数据库依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!--mybatis依赖-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
  • spring-boot-starter-web: 可以为Web开发提供支持,为我们提供了嵌入的 Servlet 容器以及 Spring MVC 的依赖,并为 Spring MVC 提供了大量自动配置。
  • mysql-connector-java:数据库驱动包。
  • mybatis-spring-boot-starter:连接 Spring BootMyBatis,构建基于 Spring BootMyBatis 应用程序。
  • lombok:简化Java代码的工具包。

数据源配置

修改 src/main/resources/application.yml 文件进行数据源的配置:

server:
  port: 8090
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/logindemo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=true
    username: root
    password: root
mybatis:
  mapper-locations: classpath:mapping/*Mapper.xml
  type-aliases-package: com.sac.demo.entity
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com:
      sac:
        demo:
          mapper : debug

application.yml 配置文件中 mybatis 字段中定义的几个属性需要关注一下。

  • mapper-locations:指定 MyBatisXML 映射文件的位置,mapping/*Mapper.xml 表示 MyBatis 会去 resources/mapping 目录下查找所有以 Mapper 结尾的 xml 文件,作为映射文件。
  • type-aliases-package:扫描实体类的位置,在此处指明扫描实体类的包,在 mapper.xml 中就可以不写实体类的全路径名。
  • map-underscore-to-camel-case:通常数据库列使用大写字母组成的单词命名,单词间用下划线分隔,而 Java 属性一般遵循驼峰命名法约定。为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true

创建实体类

根据我们之前创建的数据库 user 表,在 src/main/java/com/sac/demo 目录下创建 entity 目录,并在 entity 目录下创建对应的实体类 User.java,代码如下:

package com.sac.demo.entity;

import lombok.Data;

@Data
public class User {
  private long id;

  private String userName;

  private String password;
}

这里我用了 lombok 包提供的 Data 注解,它会自动帮我们生成 getter/settertoString 等方法,可以简化我们的 java 的代码。

注意一个细节,实体类里定义的 userName 字段是驼峰式的,而数据库里的字段user_name是带下划线的,这里能自动映射靠的就是我们之前在 application.yml 中开启的 map-underscore-to-camel-case 配置项。

创建 mapper 接口

MyBatis 中提供了两种方式来实现 SQL 语句映射,一种是通过 XML 来定义语句,还有一种是通过注解的方式,注解的方式更加简洁、方便,但是不如 XML 来的功能强大、直观,这里由于文章篇幅有限,重点介绍 XML 的形式来实现 SQL 语句映射。

首先定义一个 mapper 接口。

src/main/java/com/sac/demo 目录下创建 mapper 目录,在 mapper 目录中新建 UserMapper.java 接口文件,内容如下:

package com.sac.demo.mapper;

import com.sac.demo.entity.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper {
  int insertUser(User user);

  User getByUserNameAndPassword(User user);
}

为了能在 Spring Boot 启动的时候找到我们定义的 mapper 接口文件,还需要在启动类中通过@MapperScan("com.sac.demo.mapper") 注解指定 mapper 文件的扫描的路径:

package com.sac.demo;

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

@SpringBootApplication
@MapperScan("com.sac.demo.mapper")
public class DemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

创建 mapper XML

上节中创建的 mapper 接口文件还需要创建一个 mapper XML 文件与之对应,mapper XML 文件中主要定义了 SQL 语句。

resources/mapping 目录下创建一个 UserMapper.xml 文件,由于之前我们在 application.yml 中通过 mapper-locations 属性已经指定了映射文件的查找路径,因此 MyBatis 会自动扫描此指定包的所有 mapper 并创建实现类。

UserMapper.xml 内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sac.demo.mapper.UserMapper">
    <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into user (user_name,password) values (#{userName},#{password})
    </insert>

    <select id="getByUserNameAndPassword" parameterType="User" resultType="User">
        select *
        from user
        where user_name = #{userName}
          and password = #{password}
    </select>
</mapper>

在开发 mapper 文件过程中需要注意以下几点:

  • mapper 映射文件的 namespace 必须要和 mapper 接口的完全限定名保持一致。
  • mapper 映射文件中 statementid 必须与 mapper 接口中的方法的方法名保持一致。
  • mapper 映射文件中 statementparameterType 指定的类型必须与 mapper 接口中方法的参数类型保持一致。
  • mapper 映射文件中 statementresultType 指定的类型必须与 mapper 接口中方法的返回值类型保持一致。如果在 application.yml 文件中的 type-aliases-package 指定了扫描实体类的位置,就可以省略类的具体路径而直接写类名。
  • insert 语句中,因为 user 表的 id 是自增的,那么,如果在 SQL 中不传 id,但希望获取插入后的主键,就可以设置 useGeneratedKeys 属性。

MyBatis XML 映射器的具体用法可以参考 MyBatis 文档。

创建 service

src/main/java/com/sac/demo 目录下创建 service 目录,在 service 目录中新建 UserService.java 文件,内容如下:

package com.sac.demo.service;

import org.springframework.stereotype.Service;
import com.sac.demo.mapper.UserMapper;
import com.sac.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class UserService {
  @Autowired
  UserMapper userMapper;

  public int insertUser(User user) {
    return userMapper.insertUser(user);
  }

  public User getByUserNameAndPassword(User user) {
    return userMapper.getByUserNameAndPassword(user);
  }
}

service 中通过 @Autowired 注解注入 userMapperservice 就可以通过 userMapper 中定义的数据库方法来访问数据库。

创建 controller

src/main/java/com/sac/demo 目录下创建 controller 目录,在 controller 目录中新建 UserController.java 文件,内容如下:

package com.sac.demo.controller;
import com.sac.demo.entity.User;
import com.sac.demo.service.UserService;
import org.apache.coyote.http11.filters.VoidInputFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
  @Autowired
  private UserService userService;

  @PostMapping("user/insert")
  public Response insertUser(@RequestBody User user) {
      int result = userService.insertUser(user);
      return Response.success(result);
  }

  @PostMapping("user/getByUserNameAndPassword")
  public Response getByUserNameAndPassword(@RequestBody User user) {
      User result = userService.getByUserNameAndPassword(user);
      return Response.success(result);
  }
}

通过 @PostMapping 注解定义了两个 POST 请求,路由 user/insert 表示新增一条记录,路由 user/getByUserNameAndPassword 表示校验用户名和密码是否正确。

但是仔细看现在的 controller 还存在两个问题。

接口返回给前端的格式应当统一,这样才方便前端统一处理所有接口返回值。

接口异常的情况没有处理,应该将后端接口的异常统一处理后以错误码和错误信息的形式抛给前端,方便前端进行错误提示。

针对上面的两个问题,在 entity 目录中定义一个 Response 实体类来统一处理返回结果。

package com.sac.demo.entity;

public class Response {
  private int code;

  private String msg;

  private Object data;

  public Response() {
    super();
  }

  public Response(int code, String msg, Object data) {
    this.code = code;
    this.msg = msg;
    this.data = data;
  }

  public static Response success(Object data) {
    Response item = new Response(200, "success", data);
    return item;
  }

  public static Response failure(int errCode, String errorMessage) {
    Response item = new Response(errCode, errorMessage, null);
    return item;
  }

  public int getCode() {
    return code;
  }

  public void setCode(int code) {
    this.code = code;
  }

  public String getMsg() {
    return msg;
  }

  public void setMsg(String msg) {
    this.msg = msg;
  }

  public Object getData() {
    return data;
  }

  public void setData(Object data) {
    this.data = data;
  }
}

Response 实体提供了两个静态方法 successfailure 分别提供给调用成功和调用失败的时候使用。接口返回对象中包含 codemsgdata 三个属性。

优化后的 controller 如下:

@RestController
public class UserController {
  @Autowired
  private UserService userService;

  @PostMapping("user/insert")
  public Response insertUser(@RequestBody User user) {
    try {
      int result = userService.insertUser(user);
      return Response.success(result);
    } catch(Exception e) {
      return Response.failure(500, "服务器异常");
    }
  }

  @PostMapping("user/getByUserNameAndPassword")
  public Response getByUserNameAndPassword(@RequestBody User user) {
    try {
      User result = userService.getByUserNameAndPassword(user);
      return Response.success(result);
    } catch(Exception e) {
      return Response.failure(500, "服务器异常");
    }
  }
}

接口测试

启动 Spring Boot 后,通过 http://localhost:8090 地址就可以访问后台服务了。

我们通过 Postman 来分别测试下”新增“和”登录“两个接口。

先测试"新增"接口:

image.png

数据插入成功,接口的返回值格式也符合我们的预期。

再测试”登录“接口:

image.png

可以看到,如果用户名和密码验证成功就认为登录成功,接口会返回当前查询到的记录。

最后再测试一下异常情况,假设我们插入数据库的字段有误,接口直接就会返回错误结果。

image.png

更多精彩文章欢迎关注我的微信公众号 前端架构师笔记

源码地址

参考链接

Spring-Boot-MyBatis-学习教程

MyBatis中文官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/129731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【正点原子FPGA连载】第九章Linux图形界面的搭建摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第九章Linux图形…

单片机之震动传感器、继电器、433M无线发射接收等模块介绍及应用

目录 一、震动传感器模块 二、继电器介绍 三、433M无线发射接收模块 1、 无线控制报警器代码 2、电动车简易防盗器代码实现 一、震动传感器模块 单片机供电VCC GND接单片机 产品不震动&#xff0c;输出高电平、模块上的AO口 产品震动&#xff0c;输出低电平&#xff0c…

Python使用库(一)

Python使用库 库 就是是别人已经写好了的代码, 可以让我们直接拿来用. 荀子曰: “君子性非异也&#xff0c;善假于物也” 一个编程语言能不能流行起来, 一方面取决于语法是否简单方便容易学习, 一方面取决于生态是否完备. 所谓的 “生态” 指的就是语言是否有足够丰富的库, 来…

day11-分类和static

1.案例驱动模式 1.1案例驱动模式概述 (理解) 通过我们已掌握的知识点,先实现一个案例,然后找出这个案例中,存在的一些问题,在通过新知识点解决问题 1.2案例驱动模式的好处 (理解) 解决重复代码过多的冗余,提高代码的复用性解决业务逻辑聚集紧密导致的可读性差,提高代码的可…

【python Turtle源码】教你如何画一只迎福虎将~

前言 大家早好、午好、晚好吖 ❤ ~ 代码展示 导入模块 from turtle import * import time因代码体量有点多 这里就给大家部分展示了&#xff0c;有需要的可以文章下方名片获取哦~ &#xff08;或者评论已点赞收藏&#xff0c;求代码&#xff0c;我私你呀&#xff09; COLO…

用Python实现童年小游戏贪吃蛇

贪吃蛇游戏是有史以来最受欢迎的街机游戏之一。在这个游戏中&#xff0c;玩家的主要目标是在不撞墙或不撞墙的情况下抓住最大数量的水果。在学习 Python 或 Pygame 时&#xff0c;可以将创建蛇游戏视为一项挑战。这是每个新手程序员都应该接受的最好的初学者友好项目之一。学习…

Glove模型的原理与代码

文章目录一、背景二、原理部分1.共现矩阵2. F值的获取3. Glove公式的获取4. 损失函数的获取三、代码部分1.词表映射2. 词嵌入3. 训练函数4. 输出结果总结一、背景 GloVe模型即Global Vectors模型&#xff0c;该模型认为语料库中单词出现的统计(共现矩阵) 是学习词向量表示的无监…

将博客系统部署到云服务器上(允许外网访问)

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录访问链接测试部署简单回顾 部署普通小孩也要热爱生活&#xff01; 访问链接测试 个人博客系统 登录名&#xff1a;小小周 密码&#xff1a;xiaozhou 部署 在Linux上搭建一个Java部署环境&#xff0c;然后开始进行博…

声明式事务的属性之传播行为

声明式事务的属性之传播行为 ①介绍 当事务方法被另一个事务方法调用时&#xff0c;必须指定事务应该如何传播。例如&#xff1a;方法可能继续在现有事务中运行&#xff0c;也可能开启一个新事务&#xff0c;并在自己的事务中运行。 ②测试 Controller public class BookC…

望尘科技通过港交所聆讯:坚持深耕“体育游戏”的收获者

文|螳螂观察 作者|李永华 行将结束的2022年&#xff0c;体育大年&#xff0c;除了令人心跳加速的赛事&#xff0c;还有遍地的“黄金”。 各领域大大小小的厂商们使出浑身解数&#xff0c;掘金市场。 刚刚过去不久的世界杯&#xff0c;让这一过程到达了高潮。 广告代言、彩…

排序(完整版)

目录 一、基本概念 二、排序的分类 三、排序算法的好坏的衡量 四、五类内排序 插入排序 直接插入排序 演示&#xff1a; 关键代码&#xff1a; 完整代码 结果&#xff1a; 插入排序算法分析&#xff1a; 带哨兵的插入排序 举例&#xff1a; 关键代码 完整代码 折半…

365天深度学习训练营-第P4周:猴痘病识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 内部限免文章&#xff08;版权归 K同学啊 所有&#xff09;&#x1f366; 参考文章地址&#xff1a; &#x1f517;第P4周&#xff1a;猴痘病识别 | 365天深度学习训练营&#x1f356; 作者&#xff1a;K同学啊 | 接辅导…

Java 发送邮件

使用Java应用程序发送 E-mail 十分简单&#xff0c;但是首先你应该在你的机器上安装 JavaMail API 和Java Activation Framework (JAF) 。 您可以从 Java 网站下载最新版本的 JavaMail&#xff0c;打开网页右侧有个 Downloads 链接&#xff0c;点击它下载。您可以从 Java 网站…

从业10多年,我总结了这几款程序员必备实用工具

优秀程序员之所以优秀的原因并不一定是他写代码的速度比别人快&#xff0c;而是他解决事情的效率比别人高、副业渠道比别人广&#xff0c;所以提供工作效率的方法并不需要我们样样精通&#xff0c;提高副业收入的办法也不需要我们挖空心思&#xff0c;有时候使用好的工具就能帮…

微信小程序开发实战11_1 微信支付下单

微信支付流程图 微信支付存在多个业务流程&#xff0c;包括微信支付流程、退款流程等。本章节主要介绍微信的支付下单流程&#xff0c;图12-1是微信支付流程的交互图&#xff1a; 重点环节说明 步骤1&#xff1a;小程序端用户向商户服务器发起支付请求&#xff0c;重点是提供…

Appium基础 — webview操作(重点)

我们之前说过的所有操作&#xff0c;都是对原生页面的操作。 在手机APP中&#xff0c;除了原生页面&#xff0c;还是有webview页面&#xff08;也就是H5页面&#xff09;&#xff0c;下面我们就说说对webview页面的操作。 1、先了解什么是Hybrid&#xff08;混合&#xff09;…

【Web安全】Ysoserial 简单利用

Ysoserial 简单利用1. Java 反序列化特征2. Ysoserial 流量特征3. Ysoserial 攻击流程3.1 找到序列化接口3.2 漏洞利用3.2.1 常用命令3.2.2 使用案例4. Ysoserial 攻击原理问题参考1. Java 反序列化特征 在日志中&#xff0c;特征通常表现为 请求格式 Json、xml、soap、二进制…

拓扑排序的java代码实现过程详解

拓扑排序 在现实生活中&#xff0c;我们经常会同一时间接到很多任务去完成&#xff0c;但是这些任务的完成是有先后次序的。以我们学习java学科为例&#xff0c;我们需要学习很多知识&#xff0c;但是这些知识在学习的过程中是需要按照先后次序来完成的。从java基础&#xff0c…

中国电信携手鼎桥创新中心开展终端优选测评工作

近期&#xff0c;中国电信物联网开放实验室与鼎桥创新中心本着“优势互补、合作共赢、共同发展”的原则&#xff0c;携手联合开展了中国电信CTWing物联网市场终端优选测试&#xff0c;完成了多款行业智能终端的测评&#xff0c;为物联网市场上架产品的质量保驾护航&#xff0c;…

Node.js--》Express和路由模块的讲解使用

目录 Express Express的安装与使用 托管静态资源 nodemon Express路由 模块化路由 Express Express是基于Node.js平台&#xff0c;快速、开放、极简的Web开发框架。Express的作用和Node.js内置的http模块类似&#xff0c;是专门用来创建Web服务器的。Express的本质&…