前言

如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,本文通过注解的形式实现。

什么是 Mybatis

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

优点:

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个 jar 文件+配置几个 sql 映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis 不会对应用程序或者数据库的现有设计强加任何影响。 sql 写在 xml 里,便于统一管理和优化。通过 sql 基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
  • 解除 sql 与程序代码的耦合:通过提供 DAL 层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql 和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的 orm 字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态 sql。

缺点:

  • 编写 SQL 语句时工作量很大,尤其是字段多、关联表多时,更是如此。
  • SQL 语句依赖于数据库,导致数据库移植性差,不能更换数据库。
  • 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
  • 二级缓存机制不佳

准备工作

  • IDEA
  • JDK1.8
  • SpringBoot 2.1.3

sql 语句,创建表,插入数据:

CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('1', 'aaa', '21');
INSERT INTO `student` VALUES ('2', 'bbb', '22');
INSERT INTO `student` VALUES ('3', 'ccc', '23');

pom.xml 文件配置依赖

<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nasus</groupId>
<artifactId>mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis</name>
<description>mybatis Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<!-- 启动 web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis 依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- mysql 连接类 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid 数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- lombok 插件 用于简化实体代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

application.yaml 配置文件

spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver

实体类

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@AllArgsConstructor
@NoArgsConstructor
public class Student { @Id
@GeneratedValue
private Integer id; private String name; private Integer age; }

使用了 lombok 简化了代码。

dao 层

import com.nasus.mybatis.domain.Student;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update; @Mapper
public interface StudentMapper { @Insert("insert into student(name, age) values(#{name}, #{age})")
int add(Student student); @Update("update student set name = #{name}, age = #{age} where id = #{id}")
int update(@Param("name") String name, @Param("age") Integer age, @Param("id") Integer id); @Delete("delete from student where id = #{id}")
int delete(int id); @Select("select id, name as name, age as age from student where id = #{id}")
Student findStudentById(@Param("id") Integer id); @Select("select id, name as name, age as age from student")
List<Student> findStudentList();
}

这里有必要解释一下,@Insert 、@Update、@Delete、@Select 这些注解中的每一个代表了执行的真实 SQL。 它们每一个都使用字符串数组 (或单独的字符串)。如果传递的是字符串数组,它们由每个分隔它们的单独空间串联起来。这就当用 Java 代码构建 SQL 时避免了“丢失空间”的问题。 然而,如果你喜欢,也欢迎你串联单独 的字符串。属性:value,这是字符串 数组用来组成单独的 SQL 语句。

@Param 如果你的映射方法的形参有多个,这个注解使用在映射方法的参数上就能为它们取自定义名字。若不给出自定义名字,多参数(不包括 RowBounds 参数)则先以 "param" 作前缀,再加上它们的参数位置作为参数别名。例如 #{param1},#{param2},这个是默认值。如果注解是 @Param("id"),那么参数就会被命名为 #{id}。

service 层

import com.nasus.mybatis.domain.Student;
import java.util.List; public interface StudentService { int add(Student student); int update(String name, Integer age, Integer id); int delete(Integer id); Student findStudentById(Integer id); List<Student> findStudentList(); }

实现类:

import com.nasus.mybatis.dao.StudentMapper;
import com.nasus.mybatis.domain.Student;
import com.nasus.mybatis.service.StudentService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class StudentServiceImpl implements StudentService { @Autowired
private StudentMapper studentMapper; /**
* 添加 Student
* @param name
* @param age
* @return
*/
@Override
public int add(Student student) {
return studentMapper.add(student);
} /**
* 更新 Student
* @param name
* @param age
* @param id
* @return
*/
@Override
public int update(String name, Integer age, Integer id) {
return studentMapper.update(name,age,id);
} /**
* 删除 Student
* @param id
* @return
*/
@Override
public int delete(Integer id) {
return studentMapper.delete(id);
} /**
* 根据 id 查询 Student
* @param id
* @return
*/
@Override
public Student findStudentById(Integer id) {
return studentMapper.findStudentById(id);
} /**
* 查询所有的 Student
* @return
*/
@Override
public List<Student> findStudentList() {
return studentMapper.findStudentList();
}
}

controller 层构建 restful API

import com.nasus.mybatis.domain.Student;
import com.nasus.mybatis.service.StudentService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/Student")
public class StudentController { @Autowired
private StudentService studentService; @PostMapping("")
public int add(@RequestBody Student student){
return studentService.add(student);
} @PutMapping("/{id}")
public int updateStudent(@PathVariable("id") Integer id, @RequestParam(value = "name", required = true) String name,
@RequestParam(value = "age", required = true) Integer age){
return studentService.update(name,age,id);
} @DeleteMapping("/{id}")
public void deleteStudent(@PathVariable("id") Integer id){
studentService.delete(id);
} @GetMapping("/{id}")
public Student findStudentById(@PathVariable("id") Integer id){
return studentService.findStudentById(id);
} @GetMapping("/list")
public List<Student> findStudentList(){
return studentService.findStudentList();
}
}

测试结果

其他接口已通过 postman 测试,无问题。

源码下载:github 地址

后语

以上为 SpringBoot 实战 (九) | 整合 Mybatis 的教程,除了注解方式实现以外,Mybatis 还提供了 XML 方式实现。想了解更多用法请移步官方文档

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「一个优秀的废人」,关注后回复「1024」送你一套完整的 java 教程。



Spring Boot2 系列教程 (九) | SpringBoot 整合 Mybatis的更多相关文章

  1. Spring Boot2 系列教程(十七)SpringBoot 整合 Swagger2

    前后端分离后,维护接口文档基本上是必不可少的工作. 一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理想的状态,实际开发中却 ...

  2. Spring Boot2 系列教程(二十一)整合 MyBatis

    前面两篇文章和读者聊了 Spring Boot 中最简单的数据持久化方案 JdbcTemplate,JdbcTemplate 虽然简单,但是用的并不多,因为它没有 MyBatis 方便,在 Sprin ...

  3. Spring Boot2 系列教程 (十二) | 整合 thymeleaf

    前言 如题,今天介绍 Thymeleaf ,并整合 Thymeleaf 开发一个简陋版的学生信息管理系统. SpringBoot 提供了大量模板引擎,包含 Freemarker.Groovy.Thym ...

  4. Spring Boot2 系列教程 (十六) | 整合 WebSocket 实现广播

    前言 如题,今天介绍的是 SpringBoot 整合 WebSocket 实现广播消息. 什么是 WebSocket ? WebSocket 为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服 ...

  5. Spring Boot2 系列教程(九)Spring Boot 整合 Thymeleaf

    虽然现在慢慢在流行前后端分离开发,但是据松哥所了解到的,还是有一些公司在做前后端不分的开发,而在前后端不分的开发中,我们就会需要后端页面模板(实际上,即使前后端分离,也会在一些场景下需要使用页面模板, ...

  6. Spring Boot2 系列教程 (十八) | 整合 MongoDB

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 如题,今天介绍下 SpringBoot 是如何整合 MongoDB 的. MongoDB 简介 MongoDB 是由 C++ ...

  7. spring boot 系列之七:SpringBoot整合Mybatis

    springboot已经很流行,但是它仍需要搭配一款ORM框架来实现数据的CRUD,之前已经分享过JdbcTemplete和JPA的整合,本次分享下Mybatis的整合. 对于mybatis的使用,需 ...

  8. Spring Boot2 系列教程(二十)Spring Boot 整合JdbcTemplate 多数据源

    多数据源配置也算是一个常见的开发需求,Spring 和 SpringBoot 中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件 MyCat 去解决相关问 ...

  9. Spring Boot2 系列教程(三十)Spring Boot 整合 Ehcache

    用惯了 Redis ,很多人已经忘记了还有另一个缓存方案 Ehcache ,是的,在 Redis 一统江湖的时代,Ehcache 渐渐有点没落了,不过,我们还是有必要了解下 Ehcache ,在有的场 ...

随机推荐

  1. tsung测试xmpp遇到no_free_userid

    tsung里面可以配置xmpp的参数,设置一下 <option type="ts_jabber" name="userid_max" value=&quo ...

  2. Scrap简介

    原文:https://blog.csdn.net/ssw_1990/article/details/51254227 提到Python与网络爬虫,可能会想到urllib,urllib2,Beautif ...

  3. River Hopscotch-[二分查找、贪心]

    Description Every year the cows hold an event featuring a peculiar version of hopscotch that involve ...

  4. tf.train.string_input_producer()

    处理从文件中读数据 官方说明 简单使用 示例中读取的是csv文件,如果要读tfrecord的文件,需要换成 tf.TFRecordReader import tensorflow as tf file ...

  5. SELECT command denied to user 'username'@'ip' for table 'user'错误处理

    错误信息 使用RDS for MySQL,程序执行查询SQL时报错如下: SELECT command denied to user 'username'@'ip' for table 'user' ...

  6. React Mobile 搭建记录

    __dirname 总是指向被执行 js 文件的绝对路径,./ 会返回你执行 node 命令的路径,例如你的工作路径. path.join()方法可以连接任意多个路径字符串.要连接的多个路径可做为参数 ...

  7. CSS 手札记

    Display:Block/Flex 宽度如果不定义会尽可能的扩充外层宽度 在内容区域使用高度百分比和固定像素高度的时候外层设overflow:auto;可以把内层的高度撑开,否则外层会比内层短一截 ...

  8. 基于jquery的带事件显示功能的日历板插件calendar.js

    项目中需要用到一个日历板控件,要求能显示事件,于是想到了一年前在app项目上写的一个粗略版日历板,然后又想着这个可能以后还会用 于是我就封装了一下,能满足基本要求,如果有需要更多功能的也可以自行修改源 ...

  9. 【Python系统学习02】数据类型与类型转换

    一.数据类型 字符串 整数 浮点数 [补充中...] 1.字符串 str 字符串:英文string,简写str. name = '小石头:' print(name,'2019', '12', '24' ...

  10. 【小技巧】只用css实现带小三角的对话框样式

    一个小小的技巧: 如图所示,这种小三角,不用图片,只用css怎么实现呢? 直接上代码吧: <!DOCTYPE html> <html> <head> <tit ...