Fork me on GitHub

BiuBiu

记录、学习、生活

0%

SpringBoot系列(二)-MyBatis数据层

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。非常灵活,可定制化程度高!

简单介绍

MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

准备工作

MySQL创建一个biubiu的数据库 创建一张表 tb_user,插入一些测试数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
`name` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称',
`nickname` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`gender` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
`avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像',
`phone` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电话',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`updated_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10001 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (10003, '刘备', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10004, '孙尚香', NULL, NULL, '女', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10005, '周瑜', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10006, '小乔', NULL, NULL, '女', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10007, '诸葛亮', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10008, '黄月英', NULL, NULL, '女', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10009, '关羽', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10010, '张飞', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10011, '赵云', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10012, '黄总', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10013, '曹操', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10014, '司马懿', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10015, '貂蝉', NULL, NULL, '女', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10016, '吕布', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10017, '马超', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10018, '魏延', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10019, '孟获', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10020, '大乔', NULL, NULL, '女', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10021, '刘婵', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10022, '姜维', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10023, '廖化', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);
INSERT INTO `tb_user` VALUES (10024, '关平', NULL, NULL, '男', NULL, NULL, NULL, NULL, '2021-08-11 16:54:04', NULL);

SET FOREIGN_KEY_CHECKS = 1;

创建项目

创建一个springboot-mybatis-demo的web项目,如图

faeige.png

开始集成

  1. 引入相关依赖
    mybatis-spring-boot-starter
    mysql-connector-java
    最终的pom.xml文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    <?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">
    <parent>
    <artifactId>springboot-demo</artifactId>
    <groupId>com.biubiu</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot-mybatis-demo</artifactId>

    <properties>
    <java.version>1.8</java.version>
    <mybatis.version>2.2.0</mybatis.version>
    <fastjson.version>1.2.76</fastjson.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>${mybatis.version}</version>
    </dependency>
    <!--MySQL驱动-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <!--lombok工具-->
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    </dependency>
    <!--fastjson工具-->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>${fastjson.version}</version>
    </dependency>
    </dependencies>


    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>

    </project>
  2. 实体类

在写之前推荐一个工具,这里有个 代码生成器网站 推荐使用!

UserEntity 对应数据库的表 biubiu.tb_user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* <p>
* UserEntity
* </p>
*
* @author biubiu
* @since 2021/8/11
*/
@Data
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 主键id
*/
private Long userId;

/**
* 名称
*/
private String name;

/**
* 昵称
*/
private String nickname;

/**
* 年龄
*/
private Integer age;

/**
* 性别
*/
private String gender;

/**
* 头像
*/
private String avatar;

/**
* 电话
*/
private String phone;

/**
* 地址
*/
private String address;

/**
* 备注
*/
private String remark;

/**
* 创建时间
*/
private Date createdTime;

/**
* 更新时间
*/
private Date updatedTime;


}

  1. 数据交互层接口 UserMapper(增删改查)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* <p>
* UserMapper
* </p>
*
* @author biubiu
* @since 2021/8/11
*/
public interface UserMapper {
/**
* 新增
*/
int insert(UserEntity user);

/**
* 刪除
*/
int delete(int id);

/**
* 更新
*/
int update(UserEntity user);

/**
* 查询 根据主键 id 查询
*/
UserEntity load(int id);

/**
* 查询 分页查询
*/
List<UserEntity> pageList(int pageNum, int pageSize);

/**
* 查询 分页查询 count
*/
int pageListCount(int pageNum, int pageSize);
}

  1. 接口对应的UserMapper.xml文件

MyBatis提供两种写sql的方式,注解和xml,我个人觉得xml比较好,把代码和sql分开,便于维护。有时候sql写的复杂了注解方式有局限性,我习惯上使用xml方式。IDEA有个插件叫MyBatisX,可以从mapper到xml直接跳转,奥里给→_→

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?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.biubiu.mb.mapper.UserMapper">

<resultMap id="BaseResultMap" type="com.biubiu.mb.entity.UserEntity">
<result column="user_id" property="userId"/>
<result column="name" property="name"/>
<result column="nickname" property="nickname"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<result column="avatar" property="avatar"/>
<result column="phone" property="phone"/>
<result column="address" property="address"/>
<result column="remark" property="remark"/>
<result column="created_time" property="createdTime"/>
<result column="updated_time" property="updatedTime"/>
</resultMap>

<sql id="Base_Column_List">
user_id,
name,
nickname,
age,
gender,
avatar,
phone,
address,
remark,
created_time,
updated_time
</sql>

<insert id="insert" useGeneratedKeys="true" keyColumn="user_id" keyProperty="userId"
parameterType="com.biubiu.mb.entity.UserEntity">
INSERT INTO tb_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="null != userId and '' != userId">
user_id,
</if>
<if test="null != name and '' != name">
name,
</if>
<if test="null != nickname and '' != nickname">
nickname,
</if>
<if test="null != age and '' != age">
age,
</if>
<if test="null != gender and '' != gender">
gender,
</if>
<if test="null != avatar and '' != avatar">
avatar,
</if>
<if test="null != phone and '' != phone">
phone,
</if>
<if test="null != address and '' != address">
address,
</if>
<if test="null != remark and '' != remark">
remark,
</if>
<if test="null != createdTime and '' != createdTime">
created_time,
</if>
<if test="null != updatedTime and '' != updatedTime">
updated_time
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="null != userId and '' != userId">
#{userId},
</if>
<if test="null != name and '' != name">
#{name},
</if>
<if test="null != nickname and '' != nickname">
#{nickname},
</if>
<if test="null != age and '' != age">
#{age},
</if>
<if test="null != gender and '' != gender">
#{gender},
</if>
<if test="null != avatar and '' != avatar">
#{avatar},
</if>
<if test="null != phone and '' != phone">
#{phone},
</if>
<if test="null != address and '' != address">
#{address},
</if>
<if test="null != remark and '' != remark">
#{remark},
</if>
<if test="null != createdTime and '' != createdTime">
#{createdTime},
</if>
<if test="null != updatedTime and '' != updatedTime">
#{updatedTime}
</if>
</trim>
</insert>

<delete id="delete">
DELETE
FROM tb_user
WHERE user_id = #{userId}
</delete>

<update id="update" parameterType="com.biubiu.mb.entity.UserEntity">
UPDATE tb_user
<set>
<if test="null != userId and '' != userId">user_id = #{userId},</if>
<if test="null != name and '' != name">name = #{name},</if>
<if test="null != nickname and '' != nickname">nickname = #{nickname},</if>
<if test="null != age and '' != age">age = #{age},</if>
<if test="null != gender and '' != gender">gender = #{gender},</if>
<if test="null != avatar and '' != avatar">avatar = #{avatar},</if>
<if test="null != phone and '' != phone">phone = #{phone},</if>
<if test="null != address and '' != address">address = #{address},</if>
<if test="null != remark and '' != remark">remark = #{remark},</if>
<if test="null != createdTime and '' != createdTime">created_time = #{createdTime},</if>
<if test="null != updatedTime and '' != updatedTime">updated_time = #{updatedTime}</if>
</set>
WHERE user_id = #{userId}
</update>


<select id="load" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM tb_user
WHERE user_id = #{userId}
</select>

<select id="pageList" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM tb_user
LIMIT #{pageNum}, #{pageSize}
</select>

<select id="pageListCount" resultType="java.lang.Integer">
SELECT count(1)
FROM tb_user
</select>

</mapper>
  1. service层,包括接口和实现类
  • UserService接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    /**
    * <p>
    * UserService
    * </p>
    *
    * @author biubiu
    * @since 2021/8/11
    */
    public interface UserService {

    /**
    * 新增
    */
    public boolean insert(UserEntity user);

    /**
    * 删除
    */
    public boolean delete(int id);

    /**
    * 更新
    */
    public boolean update(UserEntity user);

    /**
    * 根据主键 id 查询
    */
    public UserEntity load(int id);

    /**
    * 分页查询
    */
    public Map<String, Object> pageList(int pageNum, int pageSize);
    }

  • UserServiceImpl实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    /**
    * <p>
    * UserServiceImpl
    * </p>
    *
    * @author biubiu
    * @since 2021/8/11
    */
    @Service
    public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public boolean insert(UserEntity user) {
    // valid
    if (user == null) {
    throw new RuntimeException("必要参数缺失");
    }

    int insert = userMapper.insert(user);
    return insert > 0;
    }

    @Override
    public boolean delete(int id) {
    int ret = userMapper.delete(id);
    return ret > 0;
    }

    @Override
    public boolean update(UserEntity user) {
    int ret = userMapper.update(user);
    return ret > 0;
    }

    @Override
    public UserEntity load(int id) {
    return userMapper.load(id);
    }

    @Override
    public Map<String, Object> pageList(int pageNum, int pageSize) {
    List<UserEntity> pageList = userMapper.pageList(pageNum, pageSize);
    int totalCount = userMapper.pageListCount(pageNum, pageSize);

    // result
    Map<String, Object> result = new HashMap<String, Object>();
    result.put("pageList", pageList);
    result.put("totalCount", totalCount);

    return result;
    }
    }

  1. UserController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* <p>
* UserController
* </p>
*
* @author biubiu
* @since 2021/8/11
*/
@RestController
@RequestMapping("/api/users")
public class UserController {

@Resource
private UserService userService;

/**
* 新增
*/
@RequestMapping("/insert")
public Object insert(UserEntity user) {
return userService.insert(user);
}

/**
* 刪除
*/
@RequestMapping("/delete")
public Object delete(int id) {
return userService.delete(id);
}

/**
* 更新
*/
@RequestMapping("/update")
public Object update(UserEntity user) {
return userService.update(user);
}

/**
* 查询 根据主键 id 查询
*/
@RequestMapping("/load")
public Object load(int id) {
return userService.load(id);
}

/**
* 查询 分页查询
*/
@RequestMapping("/pageList")
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int pageNum,
@RequestParam(required = false, defaultValue = "10") int pageSize) {
return userService.pageList(pageNum, pageSize);
}
}

配置数据库连接信息

上面写了一系列代码,唉,差点累死了,接下来轻松多了!

我们写了一些列类,下面开始连接数据库,以及MyBatis的xml文件位置。注意修改数据库连接字符串以及用户名密码!

application.properties

1
2
3
4
5
6
7
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/biubiu?useUnicode=true&characterEncoding=UTF-8&useSSL=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root

#MyBatis的xml文件,UserMapper.xml
mybatis.mapper-locations=classpath:mapper/*Mapper.xml

最后一步,在配置下mapper接口扫描,在启动类上加上一个注解@MapperScan("com.biubiu.mb.mapper")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* <p>
* MybatisApplication
* </p>
*
* @author biubiu
* @since 2021/8/11
*/
@MapperScan("com.biubiu.mb.mapper")
@SpringBootApplication
public class MyBatisApplication {

public static void main(String[] args) {
SpringApplication.run(MyBatisApplication.class, args);
}

}

开始测试

费了九牛二虎之力,终于到了验收成果的时候,有些小激动,废话不多说,开始干!

打开postman神器,开始一个一个测试我们的增删改查

faqXh6.png

faqv9K.png

  • 插入一个人
    faLPHA.png

好家伙看起来成功了,我们查一下数据库,果真成功了
faL9nH.png

成功了,那我再用接口查一把
faLCBd.png

  • 修改下这个人
    faLFAI.png

数据库看眼,是否成功
faLkNt.png

  • 删除把
    faLA4P.png

问题排除

由于我写的时候太粗心把好几个单词打错了,导致了几个Bug…要细心细心细心呀!!!

  1. 错误1
    pagenum小写了,和接口参数里对不上也会报错
    faqx1O.png

  2. 错误2
    自动生成Id我全都写成了id,这里应该是UserEntity里的UserId和数据库字段user_id
    faqzcD.png

  3. 错误3
    也是和UserEntity里的UserId不对应造成的
    faLSje.png

老铁,想请我喝哇哈哈嘛!![笑哭]