SpringBoot 注解方式快速整合Mybatis

news2024/12/24 20:13:14

序言:使用MyBatis3提供的注解可以逐步取代XML,例如使用@Select注解直接编写SQL完成数据查询,使用@SelectProvider高级注解还可以编写动态SQL,以应对复杂的业务需求。

一. 基础注解

MyBatis 主要提供了以下CRUD注解:

  • @Select

  • @Insert

  • @Update

  • @Delete

增删改查占据了绝大部分的业务操作,掌握这些基础注解的使用还是很有必要的,例如下面这段代码无需XML即可完成数据查询:

@Mapper
public interface UserMapper {
    @Select("select * from t_user")
    List<User> list();
}

使用过Hibernate的同学可能会好奇,这里为什么没有配置映射关系也能完成属性注入?在传统项目中使用过Mybatis的童鞋可能很快就反应过来,是因为在配置文件中开启了全局驼峰映射,SpringBoot中同样能够做到,并且更为简单快捷。

虽然开启了全局驼峰映射,但你可能还会质疑,如果不符合下划线转驼峰规则的字段,拿查询回来的实体对象属性将获取为null,比如上述User对象属性mobileNum和对应的数据库字段phoneNum,则查询结果为:

[
  {
    "userId": "1",
    "username": "admin",
    "password": "admin",
    "mobileNum": null
  },
  {
    "userId": "2",
    "username": "roots",
    "password": "roots",
    "mobileNum": null
  }
]

为了解决对象属性和字段驼峰不一致的问题,我们可以使用映射注解@Results来指定映射关系。

二. 映射注解

Mybatis主要提供这些映射注解:

  • @Results 用于填写结果集的多个字段的映射关系.

  • @Result 用于填写结果集的单个字段的映射关系.

  • @ResultMap 根据ID关联XML里面

例如上面的list方法,我们可以在查询SQL的基础上,指定返回的结果集的映射关系,其中property表示实体对象的属性名,column表示对应的数据库字段名。

    @Results({
            @Result(property = "userId", column = "USER_ID"),
            @Result(property = "username", column = "USERNAME"),
            @Result(property = "password", column = "PASSWORD"),
            @Result(property = "mobileNum", column = "PHONE_NUM")
    })
    @Select("select * from t_user")
    List<User> list();

查询结果如下:

[
  {
    "userId": "1",
    "username": "admin",
    "password": "admin",
    "mobileNum": "15011791234"
  },
  {
    "userId": "2",
    "username": "roots",
    "password": "roots",
    "mobileNum": "18812342017"
  }
]

为了方便演示和免除手工编写映射关系的烦恼,这里提供了一个快速生成映射结果集的方法,具体内容如下:

  /**
     * 1.用于获取结果集的映射关系
     */
    public static String getResultsStr(Class origin) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("@Results({\n");
        for (Field field : origin.getDeclaredFields()) {
            String property = field.getName();
            //映射关系:对象属性(驼峰)->数据库字段(下划线)
            String column = new PropertyNamingStrategy.SnakeCaseStrategy().translate(field.getName()).toUpperCase();
            stringBuilder.append(String.format("@Result(property = \"%s\", column = \"%s\"),\n", property, column));
        }
        stringBuilder.append("})");
        return stringBuilder.toString();
    }

在当前Main方法执行效果如下:然后我们将控制台这段打印信息复制到接口方法上即可。

三. 高级注解

MyBatis-3 主要提供了以下CRUD的高级注解:

  • @SelectProvider

  • @InsertProvider

  • @UpdateProvider

  • @DeleteProvider

见名知意,这些高级注解主要用于动态SQL,这里以@SelectProvider 为例,主要包含两个注解属性,其中type表示工具类,method 表示工具类的某个方法,用于返回具体的SQL。

@Mapper
public interface UserMapper {
    @SelectProvider(type = UserSqlProvider.class, method = "list222")
    List<User> list2();
}

工具类代码如下:

public class UserSqlProvider {
    public String list222() {
        return "select * from t_user ;
    }

四. 详细教程

对上述注解有所了解之后,我们以具体项目案例来进一步巩固这些注解的实际使用。

具体步骤

1. 引入依赖

为了方便演示,首选搭建Web环境,另外数据库选择Mysql 5.5+。

    <dependencies>
        <dependency> <!--添加Web依赖 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency> <!--添加Mybatis依赖 -->
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency><!--添加MySQL驱动依赖 -->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency><!--添加Test依赖 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2. 添加配置

这里主要是添加数据源,配置驼峰映射和开启SQL日志的控制台打印。在项目的资源目录中,添加 application.yml 配置如下:

spring:
  datasource:
    #连接MySQL
    url: jdbc:mysql://localhost:3306/socks?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
  configuration:
   #配置项:开启下划线到驼峰的自动转换. 作用:将数据库字段根据驼峰规则自动注入到对象属性。
   map-underscore-to-camel-case: true

logging:
  level:
   #打印SQL信息
   com.hehe.mapper: debug

3. 编写数据层代码

这里以我们熟悉的用户信息为例,编写UserMapper接口和本案例使用的UserSqlProvider。

3.1 UserMapper

添加UserMapper接口用于数据查询:

package com.hehe.mapper;
@Mapper
public interface UserMapper {
    /**
     * 方式1:使用注解编写SQL。
     */
    @Select("select * from t_user")
    List<User> list();

    /**
     * 方式2:使用注解指定某个工具类的方法来动态编写SQL.
     */
    @SelectProvider(type = UserSqlProvider.class, method = "listByUsername")
    List<User> listByUsername(String username);

    /**
     * 延伸:上述两种方式都可以附加@Results注解来指定结果集的映射关系.
     *
     * PS:如果符合下划线转驼峰的匹配项可以直接省略不写。
     */
    @Results({
            @Result(property = "userId", column = "USER_ID"),
            @Result(property = "username", column = "USERNAME"),
            @Result(property = "password", column = "PASSWORD"),
            @Result(property = "mobileNum", column = "PHONE_NUM")
    })
    @Select("select * from t_user")
    List<User> listSample();

    /**
     * 延伸:无论什么方式,如果涉及多个参数,则必须加上@Param注解,否则无法使用EL表达式获取参数。
     */
    @Select("select * from t_user where username like #{username} and password like #{password}")
    User get(@Param("username") String username, @Param("password") String password);

    @SelectProvider(type = UserSqlProvider.class, method = "getBadUser")
    User getBadUser(@Param("username") String username, @Param("password") String password);

}

3.2 UserSqlProvider

添加UserSqlProvider,用于生成SQL的工具类 。

package com.hehe.mapper;

/**
 * 主要用途:根据复杂的业务需求来动态生成SQL.
 * <p>
 * 目标:使用Java工具类来替代传统的XML文件.(例如:UserSqlProvider.java <-- UserMapper.xml)
 */
public class UserSqlProvider {
    /**
     * 方式1:在工具类的方法里,可以自己手工编写SQL。
     */
    public String listByUsername(String username) {
        return "select * from t_user where username =#{username}";
    }

    /**
     * 方式2:也可以根据官方提供的API来编写动态SQL。
     */
    public String getBadUser(@Param("username") String username, @Param("password") String password) {
        return new SQL() {{
            SELECT("*");
            FROM("t_user");
            if (username != null && password != null) {
                WHERE("username like #{username} and password like #{password}");
            } else {
                WHERE("1=2");
            }
        }}.toString();
    }
}

3.3 实体类User

添加实体类User

public class User {
    private String userId;
    private String username;
    private String password;
    private String mobileNum;
    //Getters & Setters
}

3.4 添加数据库记录

打开Navicat 查询窗口,然后只需下面这段脚本。

USE `SOCKS`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `USER_ID` varchar(50) ,
  `USERNAME` varchar(50) ,
  `PASSWORD` varchar(50) ,
    `PHONE_NUM` varchar(15) 
) ;

INSERT INTO `t_user` VALUES ('1', 'admin', 'admin','15011791234');
INSERT INTO `t_user` VALUES ('2', 'roots', 'roots','18812342017');

4. 编写控制层代码

package com.hehe.controller;

@RestController
@RequestMapping("/user/*")
public class UserController {

    @SuppressWarnings("all")
    @Autowired
    UserMapper userMapper;

    @GetMapping("list")
    public List<User> list() {
        return userMapper.list();
    }

    @GetMapping("list/{username}")
    public List<User> listByUsername(@PathVariable("username") String username) {
        return userMapper.listByUsername(username);
    }

    @GetMapping("get/{username}/{password}")
    public User get(@PathVariable("username") String username, @PathVariable("password") String password) {
        return userMapper.get(username, password);
    }

    @GetMapping("get/bad/{username}/{password}")
    public User getBadUser(@PathVariable("username") String username, @PathVariable("password") String password) {
        return userMapper.getBadUser(username, password);
    }

}

5. 启动和测试

启动工程后,访问 http://localhost:8080/user/list 可以查看用户列表如下:

访问 http://localhost:8080/user/list/admin 可以查询用户名为admin的信息:

五. 源码和文档

源码地址:SpringBoot-MyBatis-Annotation 欢迎各位Star,予以支持 。

https://github.com/yizhiwazi/springboot-socks

官方文档:Mybatis3-中文手册

http://www.mybatis.org/mybatis-3/zh/java-api.html

专题阅读:《SpringBoot 布道系列》

https://www.jianshu.com/p/964370d9374e

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

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

相关文章

Spring Cloud Alibaba Nacos Config - - - >@RefreshScope动态获取刷新后的配置内容

初学者不知道有没有这个疑惑&#xff1a;我明明已经在 SpringBoot 应用的 bootstrap.yml 配置文件中&#xff0c;通过 spring.cloud.nacos.config.refresh-enabledtrue 开启配置文件动态刷新了&#xff0c;为什么在 Controller 控制类中使用 Value 注解无法获取到配置文件修改后…

猿如意中的【取色器】效率工具详情介绍

目录 一、工具名称 二、下载安装渠道 2.1 什么是猿如意&#xff1f; 2.2 如何下载猿如意&#xff1f; 2.3 如何在猿如意中下载取色器&#xff1f; 三、取色器介绍 四、软件安装过程 五、软件界面 六、取色器功能特点介绍 七、取色器使用/体验感受 一、工具名称…

Typescript学习(第三弹)

泛型 定义 不预先确定的数据类型&#xff0c;具体的类型在使用的时候才确定&#xff0c;把泛型理解为代表类型的参数 泛型函数 泛型函数类型 泛型接口 引用泛型接口要指定一个类型&#xff0c;否则会报错 或者在泛型接口里指定一个默认类型 泛型类 泛型放在类的后面这样…

项目上线后我是如何通过慢查询和索引让系统快起来的

1、前言 最近对mysql的操作比较多一些&#xff0c;主要是项目上线以后&#xff0c;难免会有一些数据上的问题。开始的时候还主要由后端来处理&#xff0c;后面数据问题确实比较多&#xff0c;于是我就找后端要来服务器的账号密码&#xff0c;连上数据库顺便来看看数据的问题。…

C语言小项目-----员工管理系统

目录 项目要求&#xff1a; 考虑点&#xff1a; 实现过程 所用知识点 最终效果如下&#xff1a; 项目要求&#xff1a; 考虑点&#xff1a; 服务器端用select监听多个客户端&#xff0c;考虑点在于&#xff0c;公司内部的系统管理系统&#xff0c;不会有太多人每天都登陆&a…

【web前端开发】CSS的元素显示模式

前言 元素的显示模式可以更好的帮助我们布局页面,了解元素的显示模式,可以让我们布局页面时更加简单清晰 什么是元素显示模式 元素显示模式就是元素(标签)以什么样的方式进行显示 HTML元素一般分为块元素和行内元素两种类型 以下是块级元素和行内元素在网页中的显示: 块元…

3.神经网络-深度学习入门

3.神经网络 深度学习入门 本文的文件和代码链接&#xff1a;github地址 1.激活函数 sigmoid h(x)11e−xh(x) \frac{1}{1 e^{-x}} h(x)1e−x1​ def sigmod(x):return 1 / (1 np.exp(-1 * x))ReLU h(x){x:x>00:x≤0h(x) \left\{ \begin{array}{lr} x & : x > …

CMake静态库和动态库构建实例

任务 建⽴⼀个静态库和动态库&#xff0c;提供 HelloFunc 函数供其他程序编程使⽤&#xff0c;HelloFunc 向终端输出 Hello World 字 符串。安装头⽂件与共享库。 构建过程 构建动态库 目录结构 jyhlinuxubuntu:~/share/makefile_cmake/cmake01$ tree . ├── build #在…

m基于多用户MIMO系统的分布式可重构注水算法的matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 在单用户MIMO场景中&#xff0c;空间复用技术能够带来高数据速率的传输&#xff0c;但是也需要一些前提条件&#xff0c;比如发射端的预编码或者接收端的信道估计与信号检测。然而&#xff0c;在…

java项目-第169期ssm二手交易平台网站-ssm毕业设计_计算机毕业设计

java项目-第169期ssm二手交易平台网站-ssm毕业设计 【源码请到下载专栏下载】 《ssm二手交易平台网站》 该项目分为3个角色&#xff0c;管理员、用户、商家。 用户可以浏览前台商品并且进行购买。在个人后台可以看到自己的商品。 商家可以对商品进行商品分类管理、商品信息管理…

React 学习笔记:组件通信

组件通信 组件为什么需要通信呢&#xff1f;这是因为组件是独立且封闭的单元&#xff0c;默认情况下&#xff0c;组件只能使用自己的数据&#xff0c;但是多个组件之间不可避免的要共享某些数据&#xff0c;为了实现这些功能&#xff0c;就需要打破组件的独立封闭性&#xff0…

深度学习入门(五十九)循环神经网络——通过时间反向传播

深度学习入门&#xff08;五十九&#xff09;循环神经网络——通过时间反向传播前言循环神经网络——通过时间反向传播教材1 循环神经网络的梯度分析1.1 完全计算1.2 截断时间步1.3 随机截断1.4 比较策略2 通过时间反向传播的细节3 小结前言 核心内容来自博客链接1博客连接2希…

基于java+springboot+vue+mysql的甜品蛋糕销售商城网站

项目介绍 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中用户对网上蛋糕商城方面的要求也在不断提高&#xff0c;网上蛋糕商城得到广大用户的青睐&#xff0c;使得网上蛋糕商城的开发成为必需而且紧迫的事情。本系…

Docker笔记--使用数据卷实现容器与宿主机的数据交互

1--数据卷的介绍和作用 在 Docker 架构中&#xff0c;宿主机系统和容器之间不能直接传递数据&#xff0c;同时当容器被删除时&#xff0c;容器所有的数据都会被清除&#xff1b; 数据卷能够在宿主机与容器、容器与容器之间搭建数据传输和共享的通道&#xff0c;当容器内的目录与…

C++ 快速复习-数据类型

内置数据类型 int、unsigned int 、long、unsigned long 、short、char、signed char、bool、 long long float、double、long double 等 无符号的数据类型 主要在于 不在区分 -&#xff0c;数据波动范围变大。另外&#xff0c;值得注意的是 unsigned 类型的数据 不建议在输出…

玩以太坊链上项目的必备技能(变量作用域-Solidity之旅五)

在前文我们讲过 Solidity 是一种静态类型的语言&#xff0c;这就意味着在声明变量前需先指定类型。 而 Solidity 对变量划分了以下三种作用域范围&#xff1a; 状态变量&#xff08;State Variable&#xff09;&#xff1a; ​ 该变量的值被永久地存放在合约存储中&#xff…

JS新年倒计时

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;前端案例分…

Java---线程详解

目录 一、线程的介绍 二、线程的使用 &#xff08;1&#xff09;多线程的实现 1&#xff1a;继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;2&#xff09;设置和获取线程名称 1:继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;3&#xff09;线程…

Java学习—多线程Thread

多线程1. 线程简介1.1 普通方法和多线程1.2 程序、进程、线程2. 线程创建2.1 Thread类案例&#xff1a;下载图片2.2 Runnable接口案例&#xff1a;龟兔赛跑2.3 Callable接口3. 静态代理4. Lamda表达式5. 线程状态5.1 线程方法5.2 停止线程5.3 线程休眠5.4 线程礼让-yield5.5 Jo…

揭秘SpringMVC-DispatcherServlet之九大组件(二)

前言 上回聊到了HandlerAdapter&#xff0c;今天继续聊后面的组件。今天的主角是HandlerMapping&#xff0c;这篇文章全为他服务了。 HandlerMapping 上回说的Handler&#xff0c;我们说是处理特定请求的。也就是说&#xff0c;不是所有的请求都能处理。那么问题来了&#x…