初识mybatis
在第一节中学习了如何初始化一个项目,并且写了一个最最最最😄简单的接口,但是项目中数据肯定是来自数据库,在传统java
中使用JDBC
来操作数据库,进入web
部分后,现在主要采用mybatis持久层框架
做SQL映射(把数据库内容映射成对象,Object Relational Mapping)来操作数据库,在spring boot
中集成到了mybatis-spring-boot-starter
中。
所以本系列教程中操作数据库时第一步在pom.xml
先引入两个依赖:
引入必备依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置datasource
有了上述的starter
和mysql驱动
之后,做一个小小的改变,将resources/application.properties
文件删除。然后在此位置新建application.yml
,然后写入数据库连接配置项:
server:
port: 8082
servlet:
context-path: /api
#####################上面三行在第一节已经解释
spring:
datasource:
url: jdbc:mysql://localhost:3307/test_spring?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
其中datasource
各个字段含义:
url
:- 含义:数据库地址
- 格式:
jdbc:mysql://数据库ip:数据库端口号/数据库名字?用户编码&字符编码&服务器时区
username
:- 含义:数据库账户名称
password
:- 含义:数据库账户密码
driver-class-name
:- 含义:数据库驱动类名
使用mybatis
通常来说有两种方式来使用mybatis
:
- 使用注解
- 使用
mapper
接下来通过基本的数据库操作-查询数据库来分别实践两种方式,然后再把增删改查四种方式都实现一遍。几个约定
我是约定大于配置
的拥趸,同样的,在springboot
开发中也有一套约定,目前我觉得有两个好约定:代码结构和书写顺序: - 代码结构最好是如下的组织结构:
以上代码结构也是良好的分层结构-三层controller dao service
,其中对于service
层通常习惯面向接口(interface
)编程,具体的实现在impl
中写实现类,提高了不同业务中针对同一接口的不同实现。
- 把数据库中要用到的表用实体类映射出来
package com.wushao.springbootdemo.entity;
import java.util.Objects;
public class User {
private Integer id;
private String name;
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id.equals(user.id) &&
name.equals(user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
对于以上的属性,直接利用IDEA
的快捷键alt+insert
进行getter setter equals hashCode
的快速实现,也可以借助lombok
的注解快速实现。
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
}
- 面向顶层来写代码,也就是对接的前端展示层,即
controller层
,可以认为是接口层。
@RestController
@RequestMapping(value = "users")
public class UserController {
@Autowired
UserService userService;
@GetMapping(value = "", produces = {"application/json;charset=UTF-8"})
public List<User> getAllUsers() {
return userService.listUsers();
}
@PostMapping(value = "/getUsers", produces = {"application/json;charset=UTF-8"})
public List<User> getUsersByCondition(@RequestBody User user) {
return userService.listUsersByCondition(user);
}
}
对于control
层来说
- 首先要打上
@RestController
的注解,告诉容器我是一个restful
风格的api层 - 其次使用
@RequestMapping
注解标识接口的根路径为/users
- 使用
@Autowired
自动注入Service
层的逻辑接口。 - 使用
@GetMapping @PostMapping @PutMapping @DeleteMapping
四种注解完成Restful
接口
- 在
service
中完成业务
这一层是后端实现逻辑的主要业务层,通常来说,这一层的代码结构采用两层来进行细化(详见上图的目录结构)
- 外层是接口定义
public interface UserService {
List<User> listUsers();
List<User> listUsersByCondition(User user);
}
- 内层
impl/
去实现上面的interface
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
@Override
public List<User> listUsers() {
return userDao.findAll();
}
@Override
public List<User> listUsersByCondition(User user) {
return userDao.findUsersByCondition(user);
}
}
对于Service层
来说,使用Spring框架
的注解@Service
告诉容器我是Spring的一个Bean
service
中调用dao
层相关sql
去操作数据库
最后一步重要操作是通过ibatis
的注解@Select
操作数据库查询数据,mybatis
是它后来改的名字,也就是说必须先引入了mybatis
的依赖,才能使用@Select
。
@Repository
public interface UserDao {
@Select("select * from test_spring.user;")
List<User> findAll();
List<User> findUsersByCondition(User user);
}
对于Dao层
来说,使用Spring框架
的注解@Repository
告诉容器我是Spring的一个Bean
上述的两个注解可以帮助开发人员在Bean类
与容器入口类之间直接进行跳转。
@Select
注解后面的就是sql语句
,@Select("select * from test_spring.user;")
, 查询test_spring库的user表
完成查询数据库的操作。
使用mapper
的方式完成模糊查询
要想使用mapper
方式:
- 首先需要在配置文件
application.yml
中写入mapper
的扫描路径
# 上面的基础配置
mybatis:
mapper-locations: classpath:mapper/*.xml
- 在
resources/mapper
目录下建立对应的user-mapper.xml
,一张表一个mapper
<?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.wushao.springbootdemo.dao.UserDao">
<select id="findUsersByCondition" resultType="com.wushao.springbootdemo.entity.User" parameterType="com.wushao.springbootdemo.entity.User">
-- SELECT * FROM test_spring.user WHERE name LIKE '%${name}%'
SELECT * FROM test_spring.user WHERE name LIKE "%"#{name}"%"
</select>
</mapper>
上面的xml
中
mapper标签
的namespace
是dao层目录
select标签
表示这是查询数据库的操作,它的id
是dao层
的方法名字resultType
是实体类的路径,也是返回结果类型parameterType
的参数的类型,也是实体类。如果在dao
使用下面的写法可以不用这个参数:
// List<User> findUsersByCondition(User user);
List<User> findUsersByCondition(@Param("user") User user);
- 对于具体的
sql语句
,有如下两种模糊查询的写法
SELECT * FROM test_spring.user WHERE name LIKE '%${name}%'
SELECT * FROM test_spring.user WHERE name LIKE "%"#{name}"%"
支持dao
层和mapper
之间的跳转工具
实现效果如下图所示: