4.基础数据库操作

数据库操作这块,延续SSM的内容,我们使用MyBatis来进行数据库操作,对于MyBatis,数据库操作内容可以写在以注解形式写在Java内,同样可以以Xml形式编写,对于本篇内容,主要是前者

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software for internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs) [百度百科]

日常Copy一波百度百科,经过前两篇的内容,你应该对SpringBoot的Controller有了大致的了解,但是MVC(自行补课本部分技术补充)不能光有C(Controller),还要有M(Model),还要有V(View),我们现在讨论M部分。

你可能已经了解,举个例子,QQ空间大家都用过,那么为什么我们走到任何地方,使用任何网络,换不同的设备,只要登录你的QQ号,就可以看到你发的所有动态呢?

答案已经很明确了,你发的所有动态,都存放在腾讯的数据库里了,这写数据库可能分散在世界各地,有的可能在岛上,有的可能在山洞,这些不过多探究,有了数据库,有了持久化技术,我们可以轻松的保存数据。

那么,很抱歉,到现在才说,你看完上面的内容之后会发现重点,我们需要一样东西,那就是数据库,那么就是我们前面已经安装好的Xampp套装,其中的Mysql即我们所需要的数据库,我们可以启动它(前面已经介绍过)备用。

好了,正式开始, 先来实现简单的数据操作,然后我们就可以实现一个真正的注册登录。【折腾了这么久……好得也得看见个结果】

准备

MySql以及MySql管理工具

Postman(这里get/post请求都使用本软件即可)

前两篇内容写过的工程

Idea编程环境

1.添加依赖

这次我们的pom.xml文件就派上用场了。

在pom.xml文件的下添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--MyBatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>

<!--Mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

添加之后如下,屏幕没显示完全,只要放在dependencies里就没问题。

1547716039402

添加之后右下角会有弹窗提示下载,点击Import Changes,即可开始下载,这个文件只要有变动就会触发弹窗。

1547715774961

等待下载进度条完成后,我们打开右下角的小方块,选中Structure,就可以看到如下页卡,里面是我们下载的依赖,在这里可以看到你到底下没下成功,关闭的话可以点击左侧的Project,切换回文件目录

1547716204004

2. 配置数据库

依赖我们已经处理好了,下一步就是配置了。

不知道你还记不记得,我之前说过的配置的地方在哪里?

1
src/main/resources/application.properties

这个文件可以配置好多东西,具体是什么,我们慢慢探索

我们打开加入以下内容

1
2
3
4
5
mybatis.type-aliases-package=cn.surine.book_demo.Entities
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = root

当前效果如下

1547717145383

下面我们挨个分析每一行都是什么

1
2
mybatis.type-aliases-package=cn.surine.book_demo.Entities
#这一行是Entity对应的包名

怎么理解?

还记不记得我们之前写过一个UserEntity,我们打开看。

1547716859553

如果你的项目名,包名跟我写的不一样,红线处也不会相同。

而你要做的是需要把你自己的红线处内容填到 “ mybatis.type-aliases-package= ” 后。

这个Entities包下,将会放所有的实体类,他们直接与Model,与数据库有关联。

1
2
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
#这个是驱动。默认这么写就OK啦!

继续

1
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC

这是数据库连接的url,这里面包括几个部分。

jdbc:mysql:// : 固定标识

localhost:3306 : IP+mysql端口

/test : 数据库名

?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC : 固定的一些参数

所以重要的部分就是/test数据库名,需要改成你自己建立的,这里我们用的是test1,以后要有改动,我再另说。

如果你不使用云存储之类的设备,localhost也不需要改,否则可以改成对应的ip

1
2
spring.datasource.username = root
spring.datasource.password = root

你的数据库账号密码。

木有密码的可以写成如下

1
spring.datasource.password =

好了,这里需要按照自身情况定义的还比较多,一定仔细理解,不要照抄我的,否则会出现问题。

小提示:如果你的com.mysql.jdbc.Driver标红,说明你的项目mysql lib没设置好,检查pom.xml文件

接下来,我们配置扫描注解。

我们建立一个Mapper包,新建一个UserMapper接口,这里Mapper是用来数据库操作的。

1547717862538

同样这里我们标记了红线部分,我们把它copy下来,添加到Application中

1547718263543

这是一个MapperScan,用于Mapper扫描

1
@MapperScan(" 你的mapper包名 ")

3. 开始流程

我们前面已经实现了UserEntity,我们要用他沟通数据库与Controller。

首先我们看一下数据库

1547799606442

再贴一遍表格

名字 类型 排序规则 额外 其他
id int4 自动增长 主键
name varchar20 utf8mb4_general_ci 姓名
pswd varchar20 utf8mb4_general_ci 密码

建立数据表的命令是mysql所需要掌握的内容。

建立成功之后,我们来看一下实体类,我们把UserEntity修改为如下,也就是增加一个id字段,并且修改了构造方法和toString方法,同时我们继承了Serializable序列化接口,用于网络传输

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
package cn.surine.book_demo.Entities;

import java.io.Serializable;

public class UserEntity implements Serializable {

//前面提到了,如果不想传本参数,可以写上JsonIgnore
@JsonIgnore
private int id;
private String userName; //姓名
private String passWord = null; //密码

public UserEntity(int id, String userName, String passWord) {
this.id = id;
this.userName = userName;
this.passWord = passWord;
}

public UserEntity() {
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassWord() {
return passWord;
}

public void setPassWord(String passWord) {
this.passWord = passWord;
}

@Override
public String toString() {
return "UserEntity{" +
"id=" + id +
", userName='" + userName + '\'' +
", passWord='" + passWord + '\'' +
'}';
}
}

这里就可以添加Mapper方法了。

1
2
3
4
5
6
public interface UserMapper {
//插入用户
@Insert("INSERT INTO user(name,pswd) VALUES( #{userName}, #{passWord})")
void insert(UserEntity user);

}

我先不解释具体内容,我想你看到上述的代码的注释就可以大致理解一个东西了,插入用户,可以用来注册,那我们来实现注册。

最后一部分是Controller,在HelloController里添加内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  
//自动注入UserMapper
//@Autowired是一种注解,可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作
//我们Controller要用到UserMapper,所以要自动注入它
@Autowired
private UserMapper userMapper;

@RequestMapping(value = "/registerUser",method = RequestMethod.POST)
public String registerUser(UserEntity userEntity){
int status = userMapper.insert(userEntity);
if(status == 1){
return "注册成功";
}else{
return "注册失败";
}
}

我们调用接口

1
POST : localhost:8080/registerUser

传入相应字段,示意如下:

1547811314773

看到数据库的结果如下,记得刷新才能看到哦!(前面几次是我测试数据,最后一次才是我所指代的结果)。

1547813712858

我们开始正式解释一下上述所讲的注册流程。

当我们发送userNamepassWordlocalhost:8080/registerUser后,后端的registerUser方法接受两参数,并且映射到UserEntity对象中,自此,我们又调用了

1
int status = userMapper.insert(userEntity);

这一行,我们调用UserMapper内的insert方法,传入刚装配好的UserEntity对象,并且返回调用结果,用来反馈给前端。

那我们再看一下insert方法。

1
2
@Insert("INSERT INTO user(name,pswd) VALUES( #{userName}, #{passWord})")
void insert(UserEntity user);

这里的Mapper是一个接口,接口中定义了insert方法,而该方法上面是一个注解用于操作数据库,而后端与数据库的连接,也就是通过这句sql语句来完成的。

sql语句,应该是是属于补课内容了,其实完全可以现写现查。可以参考前面的技术补充。其中上述sql语句中的name,pswd是我们数据库的字段,对于后面的#{

userName}#{passWord}将会被我们传进来的UserEntity对象中的字段值所替代,所以你应该知道哪些字段名应该与哪些字段名所对应啦!

如果……

实在不行的话……只能全部写同样的字段咯(数据库,Mapper,Bean等等里面所有的)。

好了,对于这个注册操作,所有的内容已经说的差不多了。我们再写一个。

4. 删操作

刚我们写了增。

下面我们写删。

删对应在我们示例中,就是销毁账户咯,这次我们还是从Mapper开始写起,在写这个之前,请确保数据表里有数据,或者说刚才你已经按照我的操作实现了增。

我们写两种。

一种是按照主键(id)来删除

另一种是按照用户名来删除(这就要确保用户名唯一了,刚才我发的数据库测试图我一会会修改的,你只需要确保你的数据表中的数据用户名都是唯一的即可。)

第一种,Mapper如下,仍然写在UserMapper中

1
2
@Delete("DELETE FROM user where id = #{id}")
int delete(int id);

@Delete操作标志删除,其中的sql语句,表达的意思是从user表中,删除id = 你所要求的id 的数据

对应Controller,我们添加,是一个调用,返回状态,同增操作一样

1
2
3
4
5
6
7
8
9
@RequestMapping(value = "/deleteUser",method = RequestMethod.POST)
public String deleteUser(@RequestParam(value = "id") int id){
int status = userMapper.delete(id);
if(status == 1){
return "删除成功";
}else{
return "删除失败";
}
}

我们请求一下试试看

1547815200464

我们删除了id为2的数据,所以就出现如下情况。

1547815272360

第二种,按照用户名来注销,同上面一样咯。

1
2
@Delete("DELETE FROM user where name = #{name}")
int deleteByName(String name);
1
2
3
4
5
6
7
8
9
@RequestMapping(value = "/deleteUserByName",method = RequestMethod.POST)
public String deleteUserByName(@RequestParam(value = "userName") String userName){
int status = userMapper.deleteByName(userName);
if(status == 1){
return "删除成功";
}else{
return "删除失败";
}
}

这段代码我测试通过了,你可以自行尝试一下测试哦。

这里我提一句,我们用status来标志状态,对于增删或者修改,status标识的是影响的数据数目,比如说你用户表里有10个叫surine的用户,请求删除surine,就会返回status = 10 ,所以你可以考虑自己处理这方面的内容了。

5. 改操作

我们来做修改密码功能。

我们现在的数据库,我添加了几条数据里面,保证每一条的name都不重复

1547889713360

然后我UserMapper中添加下列内容

1
2
@Update("UPDATE user SET pswd=#{passWord} WHERE name =#{userName}")
int update(UserEntity user);

上面的语句,我相信你已经理解了,@update是更新的注解,里面是一句更新的sql语句,意思就是 查询name = 你所要求的用户名,set pswd = 新密码。

最后是Controller,还是调用,相信你已经了如指掌了。

1
2
3
4
5
6
7
8
9
@RequestMapping(value = "/changePswdUserByName",method = RequestMethod.POST)
public String changePswdUserByName(UserEntity userEntity){
int status = userMapper.update(userEntity);
if(status == 1){
return "修改成功";
}else{
return "修改失败";
}
}

重新运行后请求

1
localhost:8080/changePswdUserByName

传入相应字段,即可看见效果;

1547889907683

上面是没有surine2这个人,所以修改失败

1547889942916

这次就成功了。

我们看下数据库,刷新一下。

1547890001818

说明操作成功啦。

6.查操作

查操作有两种,一是按照条件查找,二是查找全部。我们分别来实现。

按照用户名查找:

是一个get方法,传入用户名,可以返回用户名和密码

1547890988095

这里我们看一下Mapper

1
2
3
4
5
6
@Select("SELECT * From user where name = #{name}")
@Results({
@Result(property = "userName", column = "name"),
@Result(property = "passWord", column = "pswd")
})
UserEntity getUserByName(String name);

getUserByName接受String,返回UserEntity对象。

@Select是一个查询操作,里面的sql语句是查询语句,*代表所有,上述所表示的是查询所有name = 你所指定的name

不同的是,多了一部分@Results,用于指定数据库查询返回些什么字段,其中property是实体类字段,column是数据库字段,只需要按照你的实际情况对应即可。

所以你应该明白,当我们这样写:

1
2
3
@Results({
@Result(property = "passWord", column = "pswd")
})

会出现什么情况了。

1547891336406

接下来是Controller

1
2
3
4
5
6
7
8
9
/**
* 根据用户名,获取用户信息
* @param name 用户名
* @return UserEntity 用户信息
* */
@RequestMapping(value = "/getUserByName")
public UserEntity getUserByName(@RequestParam(value = "userName") String name){
return userMapper.getUserByName(name);
}

调用getUserByName方法后,传入name,返回UserEntity对象。

全部查找,返回数据库里所有数据的列表。

Mapper如下:

1
2
3
4
5
6
@Select("SELECT * from user")
@Results({
@Result(property = "userName", column = "name"),
@Result(property = "passWord", column = "pswd")
})
List<UserEntity> getUsers();

Controller如下:

1
2
3
4
5

@RequestMapping(value = "/getUsers")
public List<UserEntity> getUsers(){
return userMapper.getUsers();
}

调用url与结果如下:

1547900138521

可以看到,我们上述,用到的四种操作,增删改查,每一种都对应了一种注解。

  • 增:@Insert
  • 删:@Delete
  • 改:@Update
  • 查:@Select

确定好你的操作,然后写上对应的注解,注解内写上相应的sql语句,然后必要的时候需要控制你返回的字段内容。

掌握了基础数据库操作之后,我们可以来实现一个项目实战。

点我回到目录