MyBatis初级实战
《MyBatis初级实战》系列旨在通过一系列编码实战,和读者一起掌握MyBatis的基本用法,帮助初学者快速运用MyBatis参与实际开发;
聚焦MyBatis
《MyBatis初级实战》面向的是对MyBatis有兴趣的读者,向读者们提供可用的方案和代码,这里不是比较Hibernate、sqltoy-orm的地方,作者也十分认可这些ORM框架,但《MyBatis初级实战》不参与比较;
关于MyBatis
引自官方:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
实战环境
《MyBatis初级实战》系列的环境信息如下:
- JDK:1.8.0_181
- mybatis-spring-boot-starter:2.1.3(对应的MyBatis:3.5.5)
- Spring Boot:2.3.2.RELEASE
- MySQL:5.7.29
- 实战环境:win10
- 开发工具:IntelliJ IDEA 2019.2.1 (Ultimate Edition)
Spring Boot集成MyBatis常规步骤概览
Spring Boot集成MyBatis的常规步骤如下:
- maven中添加mybatis-spring-boot-starter的依赖;
- Spring Boot的配置中指定MyBatis配置文件的位置;
- Spring Boot的配置中指定MyBatis映射文件的位置;
- 添加MyBatis配置文件,后续MyBatis的常规配置集中在此;
- 映射文件xxxMapper.xml及其对应的接口文件;
- 业务代码中,Autowired注解修饰接口文件并使用;
- 接下来开始实战,咱们先把数据准备好;
准备数据
- 请您自行准备好MySQL服务,我这边MySQL是部署在docker上的,可以参考《群晖DS218 部署mysql》;
- 创建名为mybatis的数据库;
- 在mybatis数据库下执行以下SQL,即可创建本次实战所需数据:
USE mybatis;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`age` int(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`user_id` int(32),
`action` varchar(255) NOT NULL,
`create_time` datetime not null,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO mybatis.user (id, name, age) VALUES (3, 'tom', 11);
INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (3, 3, 'read book', '2020-08-07 08:18:16');
源码下载
- 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
- 这个git项目中有多个文件夹,本章的应用在mybatis文件夹下,如下图红框所示:
关于父子工程
为了整个系列的代码好管理,我这边用maven创建的是父子工程,如果您只要子工程,不需要父子结构,要对子工程的pom.xml做以下调整:
- parent节点原本如下:
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
请替换成以下内容(也就是直接用>spring-boot-starter-parent作为父工程):
代码语言:javascript复制<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
- 子工程种的dependency节点中没有version子节点,这些都放在父工程的dependencyManagement中统一管理了,请您将version添加到子工程的各个dependency节点:
- 接下来开始编码
创建父工程
创建名为mybatis的maven工程,pom.xml内容如下:
代码语言:javascript复制<?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.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<modules>
<module>simple</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
- 至此,准备工作算是全部完成了,接下来咱们开始创建一个典型的Spring Boot集成MyBatis的项目吧;
Spring Boot集成MyBatis
- 在父工程mybatis之下新建名为simple的Spring Boot子工程,其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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>simple</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>simple</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- Spring Boot配置文件是simple/src/main/resources/application.yml,内容如下:
server:
port: 8080
spring:
# 数据源
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.50.43:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis配置
mybatis:
# 配置文件所在位置
config-location: classpath:mybatis-config.xml
# 映射文件所在位置
mapper-locations: classpath:mappers/*Mapper.xml
# 日志配置
logging:
level:
root: INFO
com:
bolingcavalry:
simple:
mapper: debug
- 新建user表对应的实体类User.java:
package com.bolingcavalry.simple.entity;
/**
* @Description: 实体类
* @author: willzhao E-mail: zq2599@gmail.com
* @date: 2020/8/4 8:24
*/
public class User {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{"
"id=" id
", name='" name '''
", age=" age
'}';
}
}
- 新建log表对应的实体类Log.java:
package com.bolingcavalry.simple.entity;
import java.sql.Date;
/**
* @Description: 实体类
* @author: willzhao E-mail: zq2599@gmail.com
* @date: 2020/8/4 8:24
*/
public class Log {
private Integer id;
private Integer userId;
private String action;
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Log{"
"id=" id
", userId=" userId
", action='" action '''
", createTime=" createTime
'}';
}
}
- 接下来会新建三个配置文件,先来看下它们的位置,以免后面放错地方引起不必要的麻烦:
- application.yml所在目录下,新增名为mybatis-config.xml的文件,这是mybatis的配置文件,本例很简单只有一个配置,内容如下:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<!-- 映射文件中的类不用写全路径了-->
<package name="com.bolingcavalry.simple.entity"/>
</typeAliases>
</configuration>
- resources/mappers目录下,新增名为UserMapper.xml的文件,和user表相关的查询都在此,本文只有一个查询user表的操作,注意下文中的resultType等于User,这里没有写User类的完整路径,是因为前面mybatis-config.xml文件中配置了typeAliases的package节点的缘故:
<?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.bolingcavalry.simple.mapper.UserMapper">
<select id="sel" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
</mapper>
- 再新增LogMapper.xml,如下所示,log表中的user_id字段在Log.java中没有同名的字段,因此要新增resultMap来建立数据库和实体类的字段映射关系,再在select节点用上这个关系,注意要用resultMap属性(UserMapper.xml中用的是resultType):
<?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.bolingcavalry.simple.mapper.LogMapper">
<resultMap id="logResultMap" type="Log">
<id property="id" column="id" />
<result column="user_id" jdbcType="INTEGER" property="userId" />
<result column="action" jdbcType="VARCHAR" property="action" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>
<select id="sel" parameterType="int" resultMap="logResultMap">
select * from log where id = #{id}
</select>
</mapper>
- 接下来是业务要用到的接口文件,第一个是UserMapper.java:
package com.bolingcavalry.simple.mapper;
import com.bolingcavalry.simple.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper {
User sel(int id);
}
- 第二个是LogMapper.java:
package com.bolingcavalry.simple.mapper;
import com.bolingcavalry.simple.entity.Log;
import org.springframework.stereotype.Repository;
@Repository
public interface LogMapper {
Log sel(int id);
}
- 上述两个类都使用了Repository注解,作用是避免在编码过程中,IDEA给出红线提示,如下图:
- 映射配置完毕,接下来就可以在应用中使用了,先为user做一个service类UserService.java,里面通过Autowired注解注入UserMapper的实现:
package com.bolingcavalry.simple.service;
import com.bolingcavalry.simple.entity.User;
import com.bolingcavalry.simple.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public User sel(int id){
return userMapper.sel(id);
}
}
- 再为log做service类LogService.java:
package com.bolingcavalry.simple.service;
import com.bolingcavalry.simple.entity.Log;
import com.bolingcavalry.simple.mapper.LogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LogService {
@Autowired
LogMapper logMapper;
public Log sel(int id){
return logMapper.sel(id);
}
}
- 最后是响应web请求的controller类,第一个是UserController.java:
package com.bolingcavalry.simple.controller;
import com.bolingcavalry.simple.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("user/{id}")
public String GetUser(@PathVariable int id){
return userService.sel(id).toString();
}
}
- 然后是LogController.java:
package com.bolingcavalry.simple.controller;
import com.bolingcavalry.simple.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogController {
@Autowired
private LogService logService;
@RequestMapping("log/{id}")
public String log(@PathVariable int id){
return logService.sel(id).toString();
}
}
- 最后是引导类SimpleApplication.java,注意MapperScan注解会自动扫描包路径下的所有接口,这样UserMapper和LogMapper就不用加Mapper注解了:
package com.bolingcavalry.simple;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.bolingcavalry.simple.mapper")
public class SimpleApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleApplication.class, args);
}
}
- 至此,编码完成,可以启动验证了;
验证
- 启动SpringBoot应用的方式有两种,最简单的办法是再IDEA中直接启动,如下图:
- 第二种是simple的目录下执行mvn clean package -U,就会在target目录得到文件simple-0.0.1-SNAPSHOT.jar,再执行java -jar simple-0.0.1-SNAPSHOT.jar即可启动;
- 在浏览器访问http://localhost:8080/user/3,可以得到user表的查询结果:
- 访问http://localhost:8080/log/3,可以得到log表的查询结果:
- 在控制台可以看到日志如下所示,这是我们开发期间调试问题的重要线索:
至此,入门级SpringBoot集成MyBatis的实战就完成了,接下来的系列内容会有更多实战,咱们一起来学习和掌握MyBatis的基本用法;