到目前为止,我们已经可以搭建一个 Rest API 服务了:
- 用 Druid 作为数据源和数据库连接池;
- 使用 JdbcTemplate 作为数据库的操作工具。
这篇,我们再来整合 MyBatis
作为我们框架的数据库持久层。
1. MyBatis 简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
MyBatis 本是Apache的一个开源项目 iBatis ,2010年这个项目由 Apache Software Foundation 迁移到了Google Code,并且改名为 MyBatis ,三年之后,MyBatis 于 2013年11月迁移到 Github,最终一直扎根于 Github,并开枝散叶,发展壮大。
具体更多的对 MyBatis 我们就不去介绍了,我们依然采用“所需”的开发原则,来讲述具体如何在项目中使用 MyBatis,详细的介绍可以参考 MyBatis中文官网 (请经常翻阅官网)
2. 准备好数据库
数据库表,依然用我们之前的,见:005 Spring Boot 使用 JdbcTemplate 操作数据库, 这里我们就不重复阐述。
3. 添加依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
4. 创建实体类
package com.jdz.entity;
import lombok.Data;
@Data
public class User {
private Integer uid;
private String name;
private Integer age;
private String addr;
}
注:
- 这里我们使用了 Lombok 的 @Data 注解。关于 Lombok 见: Lombok
5. 创建 Mapper 接口类
package com.jdz.mapper;
import com.jdz.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
public boolean doCreate(User user);
public boolean doDelByUid(Integer uid);
public boolean doUpdate(User user);
public User findByUid(Integer uid);
public List<User> findAll();
}
注意:
- UserMapper 增加 @Mapper
6. 创建 Mapper 对应的 xml 文件
创建 src/main/resources/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.jdz.mapper.UserMapper">
<resultMap id="BaseResultMap" type="User">
<id column="uid" property="uid" />
<result column="name" property="name" />
<result column="age" property="age" />
<result column="addr" property="addr" />
</resultMap>
<sql id="Base_Column_List">
uid, name, age, addr
</sql>
<insert id="doCreate">
insert into jdz_user(name, age, addr) values (#{name}, #{age}, #{addr})
</insert>
<update id="doUpdate" parameterType="User">
update jdz_user
<set>
<if test="name != null"> name = #{name}, </if>
<if test="age != null"> age = #{age}, </if>
<if test="addr != null"> addr = #{addr} </if>
</set>
where uid = #{uid}
</update>
<delete id="doDelByUid">
delete from jdz_user where uid=#{uid}
</delete>
<select id="findByUid" resultType="User">
select * from jdz_user where uid=#{uid}
</select>
<select id="findAll" resultMap="BaseResultMap">
select * from jdz_user
</select>
</mapper>
注:
namespace
的值必须与对应的 mapper 接口的完全限定名一致;<select>
<insert>
<delete>
中的 id 必须与 mapper 接口中的方法名一致;
7. 创建配置文件
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/app_test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&characterEncoding=utf8
username: root
password:
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml # 指定 mapper.xml 的位置
#扫描实体类的位置,在此处指明扫描实体类的包,在 mapper.xml 中就可以不写实体类的全路径名
type-aliases-package: com.jdz.entity
logging:
file:
path: logs/
注:
- 这里配置文件使用的是 application.yml 格式,application.properties 相应的配置也是一样的;
- mybatis.mapper-locations 这是 mapper 对应的 xml 文件位置,
*
是通配符 - type-aliases-packag 是实体类所在的包路径
8. 创建 service
package com.jdz.service;
import com.jdz.entity.User;
import com.jdz.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public boolean addUser(User user){
return userMapper.doCreate(user);
}
public boolean updateUser(User user) {
return userMapper.doUpdate(user);
}
public boolean delUser(Integer uid) {
return userMapper.doDelByUid(uid);
}
public User getInfo(Integer uid) {
return userMapper.findByUid(uid);
}
public List<User> getAll(){
return userMapper.findAll();
}
}
注:
- UserService 使用 @Service 注解
- userMapper 使用 @Autowired 注解
9. 创建 controller
package com.jdz.controller;
import com.jdz.entity.User;
import com.jdz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/user/add")
public String addUser(User user) {
userService.addUser(user);
return "ok";
}
@RequestMapping("/user/save")
public boolean saveUser(User user) {
return userService.updateUser(user);
}
@RequestMapping("/user/del")
public String delUser(Integer uid) {
userService.delUser(uid);
return "ok";
}
@RequestMapping("/user/info")
public User info(Integer uid) {
return userService.getInfo(uid);
}
@RequestMapping("/user/list")
public List<User> userList() {
return userService.getAll();
}
}
完整的目录接口:
javaapp
├─pom.xml
├─src
| ├─main
| | ├─resources
| | | ├─application.yml
| | | ├─mapper
| | | | └UserMapper.xml
| | ├─java
| | | ├─com
| | | | ├─jdz
| | | | | ├─App.java
| | | | | ├─service
| | | | | | └UserService.java
| | | | | ├─mapper
| | | | | | └UserMapper.java
| | | | | ├─entity
| | | | | | └User.java
| | | | | ├─controller
| | | | | | └UserController.java
| | | | | ├─config
| | | | | | ├─MyDuridConfig.java
| | | | | | └MyFastJsonConfig.java
到此,一个整合了 MyBatis 的 Spring Boot 就完成了,启动程序,并访问相应的接口后,就有相应的数据返回。
说说我个人在使用 MyBatis 上的体会:
- MyBatis 从某种层面上,是把与数据库相关的 SQL 语句与 java 的业务代码抽离出来,放进了 xml 里面,使繁杂的 SQL 相关的操作与业务代码解耦,在任务分块方面也更清晰;
- java 程序员只关注具体的逻辑代码的实现,而不需要去关注具体的数据是如何处理的;
- 数据库相关的开发人员,只关注 SQL 语句的实现和优化以及数据的提供;
- 同时,如果底层的数据(或数据库)有变更,都不会影响代码的处理;i
缺陷就是要维护和处理 xml 格式的 SQL,这写久了SQL嵌入代码里程序员来说,会有些不适应。
源码: