1. 引入Mybatis
项目初始化完成之后,可以在 pom.xml 文件中看到如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</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>
2. 创建数据
* 我们使用 Navicat 连接 MySql 数据库,在 Navicat 图形界面中创建一些简单的数据,这里使用KBAQ的知识库数据,表名为nlpccqa
3. 创建程序目录
我们在 com.example 目录下新建四个目录,分别是 controller、dao、entity、service。
controller层负责具体的业务模块流程的控制
entity层用于存放我们的实体类,与数据库中的属性值基本保持一致,实现set和get的方法
dao层主要是做数据持久层的工作,负责与数据库联络,封装了增删改查基本操作
service层主要负责业务模块的逻辑应用设计,具体要调用到已定义的DAO层的接口
然后在 resource 目录下新建 mapper 目录。这个 mapper 目录是用来存放 SQL 语句的地方。
顺便提一下,我们知道的 MVC 框架,即 model-view-controller 三层架构。这里 model层=entity层,与数据库的数据表对应,view层和 controller层结合非常紧密,需要联合起来一起开发。可以简单理解为 view层是做前端界面的展示,controller层做业务模流程块的控制。
如果在网上看到有 mapper层这个概念,就记住,mapper层=dao层,就是对数据库进行数据持久化操作。
不管是什么框架,我们很多时候都会与数据库进行交互。如果遇到一个场景我们都要去写SQL语句,那么我们的代码就会很冗余。所以,我们就想到了把数据库封装一下,让我们的数据库的交道看起来像和一个对象打交道,这个对象通常就是DAO。当我们操作这个对象的时候,这个对象会自动产生SQL语句来和数据库进行交互,我们就只需要使用DAO就行了。通常我们在DAO层里面写接口,里面有与数据打交道的方法。SQL语句通常写在mapper文件里面的。
Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。
4. 理解后台访问流程
————————————————
用户从页面前端,也就是我们所说的 view 层进行查询访问,进入到 controller 层找到对应的接口,接 着 controller 进行对 service 层进行业务功能的调用,service 要进入 dao 层查询数据,dao 层调用 mapper.xml 文件生成 sql 语句到数据库中进行查询。
在数据库中查询到数据,dao 层拿到实体对象的数据,接着交付给 service 层,接着 service 进行业务 逻辑的处理,返回结果给 controller,controller 根据结果进行最后一步的处理,返回结果给前端页 面。
创建一个访问用户信息的流程为:entity->dao->mapper->service->controller,这里 mapper 指的是存放 SQL 语句的 xml 文件。
5. 核心文件配置
这里我们可以使用 application.properties 文件,也可以使用 application.yml 文件来进行配置,当然推荐使用 application.yml 文件。
如果用 application.yml 在第一次启动项目的时候报错,项目右侧 maven -> lifecycle -> clean一下即可。
参数解读:
- driver-class-name:mysql驱动
- url:mysql连接的url,默认是3306端口,zzz是数据库名,useSSL是使用安全套阶层连接进行数据传输(如果true出错可以选择false),serverTimezone设置时区,亚洲时区请设置上海或者香港,不要设置北京,因为系统里没有这个时区。
- username 是用户名,password 是密码
mybatis.mapper-locations:用于将配置路径下的 * .xml 文件加载到 mybatis 中
# 方法一:只有一个路径 mybatis.mapper-locations= classpath:mapper/*.xml # 方法二:有多个路径 mybatis.mapper-locations= classpath:mapper/*.xml,classpath:mapper/user/*.xml
- type-aliases-package:指定POJO扫描包来让 mapper.xml 文件的 resultType 自动扫描到自定义POJO,这样就不用每次指定完全限定名
* # mapper.xml文件中设置
# 完全限定名
<select id="getUsers" resultType="com.example.entity.User">
# 指定了POJO扫描包之后
<select id="getUsers" resultType="User">
————————————————
6. 编写entity
我们在编写entity时遵循POJO的思想。这里需要提及“POJO最小侵入性编程”的概念,POJO(Plain Ordinary Java Object)意思是普通Java对象。类的成员是私有的,且有一系列的 setter and getter方法来提供访问。
POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。POJO的格式是用于数据的临时传递,它只能装载数据,作为数据存储的载体,而不具有业务逻辑处理的能力。
一般来讲,是 entity 中要取的数据应该和数据表相对应,但不一定要全部取出。
我们在刚才建立的 entity 目录中新建 User 类,定义属性 id、username、age。
————————————————
7. 编写Dao
springboot 集成 mybatis 开发有两种版本,注解版和配置文件版。
注解版不需要配置任何文件,拿来即用,主要依靠的是注解来生成 sql 语句。配置文件版与注解版相比,仅仅稍微复杂一点,两者的区别仅为mapper层处理的处理方式不一样。配置文件版多了一个xml文件,但是配置更加灵活,逻辑结构更加清晰,可读性更强。
注解版,用 @Mapper 注解标识,我们使用#{id}来标识参数。@Mapper 注解把 mapper 这个 DAO 交给 Spring 管理,不再写 mapper 映射文件
@Mapper
public interface UserDao {
@Select("select * from user where id=#{id}")
public User getUserById(int id);
@Delete("delete from user where id=#{id}")
public int deleteUserById(int id);
}
配置文件版,需要给编写的 dao 增加注解 @Repository。
@Repository注解修饰哪个类,则表明这个类具有对对象进行CRUD(增删改查)的功能。
而且@Repository是@Component注解的一个派生品,所以被@Repository注解的类可以自动的被@ComponentScan 通过路径扫描给找到。因此@Repository注解的类也能@Autowired实现自动装配。
通常将dao接口注入到service层的时候,需要写@Resource这个注解。加上@Repository,就是springboot生成一个bean,自动注入service的相关引用中。
我们在 dao 目录中新建 UserDao 接口,定义好方法。
使用@Param进行传参,当映射器需要多个参数时,这个注解可以 给映射器方法的每个参数来取个名字,这里有两点好处:
- 在 xml 文件中不需要再指定参数类型 parameterType,使用@Param注解来声明参数时,如果使用 #{} 或 ${} 的方式都可以,当你不使用@Param注解来声明参数时,必须使用使用 #{}方式。如果使用 ${} 的方式,会报错
- 当传递对象时,使用 #{对象.属性} 可以更清晰地提示自己
采用#{}的方式把@Param注解括号内的参数进行引用(括号内参数对应的是形参如 Userid对应的是id);在这里给参数配置@param注解后,Mybatis会自动将参数封装成Map类型,而@param注解的值会成为Map中的key,因此在sql中可以通过配置的注解值来使用参数。
使用配置文件版时,我们还需要在主程序中通过使用@MapperScan可以指定要扫描的Mapper类的包的路径。
@MapperScan是要spring启动时,扫描到所有的Mapper文件,并生成代理类交给spring容器管理;
8. 编写Mapper
在 mapper 目录下新建 UserMapper.xml 文件。
mapper.xml 的文件头信息我们一般不会去记忆,都是直接从官网给出的教程中复制 xml 的头信息,网址是:https://mybatis.org/mybatis-3...
<?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.example.demo.dao.UserDao">
<select id="getUserById" resultType="User">
select * from `user` where id=#{Userid}
</select>
<select id="getUserByAge" resultType="User">
select * from `user` where age=#{age}
</select>
</mapper>
查询的话我们用 select 标签,id 指定为方法名,resultType指明返回类型,标签中间写 SQL 语句。因为我们在yml里已经配置了 type-aliases-package: com.example.demo.entity,直接写 User 即可。 不需要完全限定名。
编写 Mapper.xml 文件主要注意三点:
- namespace相对应dao接口
- id相对应dao方法
- resultType相对应返回类型
9. 编写Service
我们需要在实现类中使用 @Service 注解,才能被 SpringBoot 扫描,在 Controller 中使用 @Autowired 注入service,在 service 中使用 @Autowired 自动装配UserDao
package com.example.demo.service;
import com.example.demo.dao.UserDao;
import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("UserService")
public class UserService {
@Autowired
private UserDao userDao;
public User queryUser(int id){
return userDao.getUserById(id);
}
public List<User> findAge(int age){
return userDao.getUserByAge(age);
}
}
10. 编写Controller
在 controller 目录中新建 UserController 类
这里我们使用 Restful 风格,直接返回数据。
使用 @Autowired 注解自动装配 UserService。编写接口为 UserService 传输数据
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getUser")
public User getUser(@RequestParam("id") int id){
return userService.queryUser(id);
}
@GetMapping("/age")
public List<User> AgeGet(@RequestParam("age") int age){
return userService.findAge(age);
}
}
11. 测试接口
返回了age=4 的所有用户的 JSON 数据。采用 get 方式传输的,所以必须使用 GetMapping。
返回了id=3的用户数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。