数据库和SpringBoot基础01
数据库
- 学习数据库主要学习的是如何对数据进行增删改查操作.
SQL
Structured Query Language: 结构化查询语言, 通过此语言让程序员和数据库软件进行交流
刘德华 30 5000
insert into emp values("刘德华",30,5000);
DBMS
DataBaseManagementSystem: 数据库管理系统(数据库软件)
常见的几种DBMS:
- MySQL: Oracle公司产品, 08年被Sun公司收购, 09年Sun公司被Oracle收购. 开源产品 , MaraDB实际上就是MySQL的一个分支使用方式和MySQL一样. 市占率排名第一
- Oracle: Oracle公司产品, 闭源产品 ,性能最强 价格最贵, 市占率排名第二
- SQLServer: 微软公司产品, 闭源产品 , 市占率第三
- DB2: IBM公司产品
- SQLite: 轻量级数据库, 安装包几十K ,只具备最基础的增删改查功能.
如何连接数据库执行SQL语句
- 执行SQL语句需要先和数据库软件建立链接之后
- 从开始菜单中找到MariaDB或MySQL,然后打开找到里面的MySQL Client 打开 , 然后输入密码后回车
退出指令: exit 登录指令: mysql -uroot -p
数据库和表的概念
在MySQL数据库软件中保存数据,需要先建库,然后在库里面建表,然后把数据保存到表中
SQL语句格式:
- 以;号结尾
- 关键字不区分大小写
- 可以有空格或换行但一定要以;结尾
数据库相关的SQL语句
1、查询所有数据库
格式: show databases;
2、创建数据库
格式: create database 数据库名 charset=utf8/gbk;
举例:
- create database db1;
- create database db2 charset=utf8;
- create database db3 charset=gbk;
3、查看数据库信息
格式: show create database 数据库名;
举例:
- show create database db1;
- show create database db2;
- show create database db3;
4、删除数据库
格式: drop database 数据库名;
举例:
- drop database db3;
- drop database db2;
- show databases;
5、使用数据库
执行表相关和数据相关的SQL语句之前必须先使用了某个数据库
格式: use 数据库名;
举例: use db1;
表相关的SQL语句
执行表相关的SQL语句必须已经使用了某个数据库 use db1;
1、创建表
格式: create table 表名(字段1名 类型,字段2名 类型,.......);
举例:
- create table person(name varchar(50),age int);
- create table student(name varchar(50),chinese int,math int,english int)charset=utf8;
创建一个员工表emp 保存名字,工资和工作
create table emp(name varchar(50),salary int,job varchar(20));
2、查询所有表
格式: show tables;
3、查询表信息
格式: show create table 表名;
举例: show create table emp;
4、查询表字段
格式: desc 表名;
5、修改表名
格式: rename table 原名 to 新名;
举例: rename table student to stu;
6、删除表
格式: drop table 表名;
UTF8字符集
- 目前utf8 和utf8mb3 一样 ,代表的是 用3个字节表示一个字符 (mb3=most byte 3)
- utf8mb4 最多不超过4个字节表示一个字符
表相关SQL(续)
使用db1数据库 use db1;
1、添加表字段
- 最后面添加格式: alter table 表名 add 字段名 类型;
- 最前面添加格式: alter table 表名 add 字段名 类型 first;
- 在xxx字段后面添加: alter table 表名 add 字段名 类型 after xxx;
举例:
- alter table emp add gender varchar(5);
- alter table emp add id int first;
- alter table emp add dept varchar(20) after name;
2、删除表字段
格式: alter table 表名 drop 字段名;
举例: alter table emp drop dept;
3、修改表字段
格式: alter table 表名 change 原名 新名 新类型;
举例: alter table emp change job dept varchar(5);
表相关SQL语句回顾:
- 创建表 create table t1(name varchar(20),age int) charset=utf8/gbk;
- 查询所有表 show tables;
- 查询表信息 show create table t1;
- 查询表字段 desc t1;
- 删除表 drop table t1;
- 修改表名 rename table t1 to t2;
- 添加表字段 alter table t1 add age int first/after xxx;
- 删除表字段 alter table t1 drop age;
- 修改表字段 alter table t1 change 原名 新名 新类型;
数据相关SQL
- 操作数据必须保证已经使用了某个数据库并且已经准备好了保存数据的表
- create database mydb5 charset=utf8;
- use mydb5;
- create table person(name varchar(50),age int)charset=utf8;
1、往表中插入数据
- 全表插入格式: insert into 表名 values(值1,值2);
- 指定字段插入格式: insert into 表名(字段1名,字段2名)values(值1,值2);
举例:
- insert into person values('tom',18);
- insert into person(name) values('jerry');
- insert into person values('aaa',10),('bbb',20),('ccc',30);
- insert into person(name) values('xxx'),("yyy"),("zzz");
2、查询数据
格式: select 字段信息 from 表名 where 条件;
举例:
insert into person values('刘备',40),('关羽',30),('悟空',20),('八戒',10),('张学友',5);
- select name from person;
- select name,age from person;
- select * from person;
- select * from person where age=50;
- select age from person where name="悟空";
3、修改数据
格式: update 表名 set 字段名=值 where 条件;
举例:
- update person set age=88 where name='刘备';
- update person set name='张飞',age=18 where name='关羽';
- update person set name='黎明' where age=5;
4、删除数据
格式: delete from 表名 where 条件;
举例:
- delete from person where name='张飞';
- delete from person where age<30;
- delete from person;
数据相关SQL
create database day2db charset=utf8;
use day2db;
create table person(name varchar(50),age int)charset=utf8;
insert into person values("刘德华",50);
中文问题:
- 错误原因是客户端和MySQL之间编解码字符集不一致导致的
- 解决方案: 修改MySQL的解码字符集为gbk
set names gbk;
综合练习题:
1. 创建数据库day1db 字符集utf8并使用
create database day1db charset=utf8;
use day1db;
2. 创建t_hero表, 有name字段 字符集utf8
create table t_hero(name varchar(50))charset=utf8;
3. 修改表名为hero
rename table t_hero to hero;
4. 最后面添加价格字段money, 最前面添加id字段, name后面添加age字段
alter table hero add money int;
alter table hero add id int first;
alter table hero add age int after name;
5. 表中添加以下数据: 1,李白,50,6888 2,赵云,30,13888 3,刘备,25,6888
insert into hero values(1,'李白',50,6888),(2,'赵云',30,13888),(3,'刘备',25,6888);
6. 查询价格为6888的英雄名
select name from hero where money=6888;
7. 修改刘备年龄为52岁
update hero set age=52 where name='刘备';
8. 修改年龄小于等于50岁的价格为5000
update hero set money=5000 where age<=50;
9. 删除价格为5000的信息
delete from hero where money=5000;
10. 删除表, 删除数据库
drop table hero;
drop database day1db;
主键约束
主键: 表示数据唯一性的字段称为主键
约束: 创建表时给表字段添加的限制条件
主键约束: 限制主键的值 唯一且非空
如何使用:
- use day2db;
- create table t1 (id int primary key,name varchar(50))charset=utf8;
- insert into t1 values(1,"aaa");
- insert into t1 values(1,"bbb"); //报错 主键值重复
- insert into t1 values(null,"ccc"); //报错 主键值为空
主键约束+自增
- 自增规则: 从历史最大值基础上+1
- 如何使用: create table t2(id int primary key auto_increment,name varchar(50))charset=utf8;
- insert into t2 values(null,"aaa");
- insert into t2 values(null,"bbb");
- insert into t2 values(10,"ccc");
- insert into t2 values(null,"ddd");
- delete from t2 where id>=10;
- insert into t2 values(null,"eee");
SQL语句分类
- DDL: 数据定义语言,包括数据库相关和表相关的SQL语句
- DML: 数据操作语言, 包括增删改查
- DQL: 数据查询语言, 只包含select查询相关的SQL语句
- TCL: 事务控制语言
- DCL: 数据控制语言
数据类型
1、整数: int(m)和bigint(m) m代表显示长度, m=5 存18 查询得到00018
create table t3(age int(5) zerofill);
insert into t3 values(18);
select * from t3;
2、浮点数: double(m,d) m代表总长度,d代表小数长度 , 存23.212 m=5 d=3
create table t5(price double(5,3));
insert into t5 values(23.32123);
insert into t5 values(233.32123); //报错
3、字符串:
char(m), 固定长度, m=10 存abc 占10, 执行效率略高, 当保存数据的长度相对固定时使用, 最大值255
varchar(m),可变长度,m=10 存abc 占3,更节省空间, 最大值65535 但推荐保存短的数据(255以内)
text(m),可变长度, 最大值65535,建议保存长度大于255的
4、日期:
date, 只能保存年月日
time, 只能保存时分秒
datetime, 保存年月日时分秒, 默认值为null , 最大值 9999-12-31
timestamp(时间戳,距离1970年1月1日的毫秒数),保存年月日时分秒,默认值为当前系统时间,最大值 2038-1-19
实例:
create table t6(t1 date,t2 time,t3 datetime,t4 timestamp);
insert into t6 values("2022-5-15",null,null,null);
insert into t6 values(null,"14:20:25","2011-10-22 10:20:30",null);
导入*.sql批处理文件
1、从老师工程中得到emp.zip 从idea中复制粘贴到 某个磁盘的根目录 ,然后右键解压到当前文件夹, 在根目录下出现emp.sql文件
2、在客户端中 执行 source f:/emp.sql;
3、执行以下SQL语句 检查是否成功
show tables; //检查是否出现了 emp和dept两个表
select * from emp; //检查是否出现了数据, 如果出现乱码 执行set names utf8; 如果格式错乱 正常
去重distinct
1、查询员工表中所有不同的工作
select distinct job from emp;
2、查询员工表中出现了哪几个不同的部门id?
select distinct dept_id from emp;
is null和is not null
1、查询有领导的员工姓名和领导id
select name,manager from emp where manager is not null;
2、查询没有领导的员工姓名
select name from emp where manager is null;
and 和 or
1、查询1号部门工资高于2000的员工信息
select * from emp where dept_id=1 and sal>2000;
2、查询3号部门或工资等于5000的员工信息
select * from emp where dept_id=3 or sal=5000;
3、查询出孙悟空和猪八戒的员工信息
select * from emp where name="孙悟空" or name="猪八戒";
比较运算符 > < >= <= = !=和<>
1、查询工资大于等于3000的员工信息
select * from emp where sal>=3000;
2、查询工作不是程序员的员工信息(两种写法)
select * from emp where job!="程序员";
select * from emp where job<>"程序员";
between x and y 两者之间
1、查询工资在2000到3000之间的员工信息
select * from emp where sal>=2000 and sal<=3000;
select * from emp where sal between 2000 and 3000;
select * from emp where sal not between 2000 and 3000;
in关键字
1、查询工资等于5000,1500,3000的员工信息
select * from emp where sal=5000 or sal=1500 or sal=3000;
select * from emp where sal in(5000,1500,3000);
select * from emp where sal not in(5000,1500,3000);
综合练习题
1、查询1号部门有哪几种不同的工作
select distinct job from emp where dept_id=1;
2、查询1号部门中有上级领导的员工信息
select * from emp where dept_id=1 and manager is not null;
3、查询工作是程序员,销售和人事的员工信息
select * from emp where job in("程序员","销售","人事");
4、查询工资不在1000-2000之间的员工信息
select * from emp where sal not between 1000 and 2000;
5、查询有奖金的员工信息
select * from emp where comm>0;
模糊查询like
- %: 代表0或多个未知字符
- _:代表1个未知字符
- 举例:
- 以x开头 x%
- 以x结尾 %x
- 包含x %x%
- 第二个字符是x _x%
- 以x开头以y结尾 x%y
- 第二个是x倒数第三个是y _x%y__
1、查询名字姓孙的员工信息
select * from emp where name like "孙%";
2、查询名字以精结尾的员工姓名
select name from emp where name like "%精";
3、查询工作第二个字是售的员工姓名和工作
select name,job from emp where job like "_售%";
4、查询名字中包含僧并且工资大于2000的员工姓名和工资
select name,sal from emp where name like "%僧%" and sal>2000;
排序order by
格式: order by 字段名 asc(升序默认)/desc(降序)
description描述
descend 降序
1、查询所有员工姓名和工资并按照工资升序排序
select name,sal from emp order by sal;
select name,sal from emp order by sal asc;
2、查询所有员工姓名和工资并按照工资降序排序
select name,sal from emp order by sal desc;
3、查询所有员工姓名,工资和部门id并且按照部门id升序排序,如果部门id一致则按照工资降序排序
select name,sal,dept_id from emp order by dept_id,sal desc;
分页查询
格式: limit 跳过的条数,请求的条数(每页的条数)
跳过的条数=(请求的页数-1)*请求的条数(每页条数)
举例:
- 查询第1页的5条数据(1-5条) limit 0, 5
- 查询第2页的5条数据(6-10条) limit 5, 5
- 请求第1页的10条数据 limit 0,10
- 请求第3页的10条数据 limit 20,10
- 请求第8页的10条数据 limit 70,10
- 请求第6页的8条数数据 limit 40,8
1、查询工资最低的3个员工信息
查询按照工资升序排序的第一页的3条数据
select * from emp order by sal limit 0,3;
2、按照入职日期(hiredate) 升序排序 查询第3页的3条数据
select * from emp order by hiredate limit 6,3;
3、查询工资最高的员工信息
select * from emp order by sal desc limit 0,1;
4、查询按照工资降序第2页的5条数据
select * from emp order by sal desc limit 5,5;
综合练习题
1. 查询员工表中3号部门工资高于1500的员工信息
select * from emp where dept_id=3 and sal>1500;
2. 查询2号部门员工或者没有领导的员工信息
select * from emp where dept_id=2 or manager is null;
3. 查询有领导的员工姓名,工资按照工资降序排序
select name,sal from emp
where manager is not null order by sal desc;
4. 查询2号和3号部门的员工姓名和入职日期hiredate按照入职日期降序排序
select name,hiredate from emp where dept_id in(2,3) order by hiredate desc;
5. 查询名字中包含僧和包含精的员工姓名
select name from emp where name like "%僧%" or name like "%精%";
6. 查询工资高于2000的工作有哪几种?
select distinct job from emp where sal>2000;
7.查询工资升序第4页的2条数据
select * from emp order by sal limit 6,2;
别名
select name as "姓名" from emp ;
select name "姓名" from emp ;
select name 姓名 from emp ;
聚合函数
通过聚合函数可以对查询的多条数据进行统计查询,统计查询的方式包括:求平均值, 求最大值,求最小值,求和,计数
1、平均值avg(字段名)
- 查询1号部门的平均工资
select avg(sal) from emp where dept_id=1;
- 查询销售的平均工资
select avg(sal) from emp where job="销售";
2、最大值max(字段名)
- 查询程序员的最高工资
select max(sal) from emp where job="程序员";
3、最小值min(字段名)
- 查询3号部门的最低工资
select min(sal) from emp where dept_id=3;
4、求和sum(字段名)
- 查询2号部门的工资总和
select sum(sal) from emp where dept_id=2;
5、计数count(*)
- 查询程序员的数量
select count(*) from emp where job="程序员";
数值计算 + - * / %
1、查询每个员工的姓名,工资和年终奖(年终奖=5个月的工资)
select name,sal,sal*5 年终奖 from emp;
2、给3号部门的员工每人涨薪5块钱
update emp set sal=sal+5 where dept_id=3;
分组查询 group by
格式: group by 分组的字段名
1、查询每个部门的平均工资
select dept_id,avg(sal) from emp group by dept_id;
2、查询每个部门的最高工资
select dept_id,max(sal) from emp group by dept_id;
3、查询每种工作的最高工资
select job,max(sal) from emp group by job;
4、查询每种工作的人数
select job,count(*) from emp group by job;
5、查询每个部门工资高于2000的人数
select dept_id,count(*) from emp where sal>2000 group by dept_id;
6、查询每个部门有领导的员工的人数
select dept_id,count(*) from emp where manager is not null group by dept_id;
having
- where后面只能写普通字段的条件,不能包含聚合函数
- having后面可以包含聚合函数的条件,需要和group by结合使用,写在group by的后面
1、查询每个部门的平均工资要求平均工资高于2000
select dept_id,avg(sal) from emp group by dept_id having avg(sal)>2000;
2、查询每种工作的人数,只查询人数大于1 的
select job,count(*) from emp group by job having count(*)>1;
select job,count(*) c from emp group by job having c>1;
3、查询每个部门的工资总和,只查询有领导的员工, 并且要求工资总和大于5400
select dept_id,sum(sal) s from emp where manager is not null group by dept_id having s>5400;
4. 查询每个部门的平均工资, 只查询工资在1000到3000之间的,并且过滤掉平均工资低于2000的
select dept_id,avg(sal) a from emp where sal between 1000 and 3000 group by dept_id having a>=2000;
各个关键字的书写顺序
select 查询的字段信息 from 表名 where 普通字段条件 group by 分组字段名 having 聚合函数条件 order by 排序字段名 limit 跳过条数,请求条数;
子查询(嵌套查询)
1、查询工资大于2号部门平均工资的员工信息
select avg(sal) from emp where dept_id=2;
select * from emp where sal>(select avg(sal) from emp where dept_id=2);
2、查询工资高于程序员最高工资的员工信息
select max(sal) from emp where job="程序员";
select * from emp where sal>(select max(sal) from emp where job="程序员");
3、查询工资最高的员工信息
select max(sal) from emp;
select * from emp where sal=(select max(sal) from emp);
4、查询和孙悟空相同工作的员工信息
select job from emp where name="孙悟空";
select * from emp where job=(select job from emp where name="孙悟空") and name!="孙悟空";
5、查询拿最低工资员工的同事们的信息(同事指同一部门)
select min(sal) from emp;
select dept_id from emp where sal=(select min(sal) from emp);
select * from emp where dept_id=(select dept_id from emp where sal=(select min(sal) from emp)) and sal!=(select min(sal) from emp);
关联关系
指创建的表和表之间存在的业务关系
有哪几种关系?
一对一: 有AB两张表,A表中的一条数据对应B表中的一条数据, 同时B表中的一条数据也对应A表中的一条数据
一对多:有AB两张表,A表中的一条数据对应B表中的多条数据, 同时B表中的一条数据对应A表中的一条数据
多对多:有AB两张表,A表中的一条数据对应B表中的多条数据, 同时B表中的一条数据也对应A表中的多条数据
表和表之间如何建立关系 ,通过外键字段建立关系:
- 一对一: 在任意表中添加一个建立关系的字段指向另外一张表的主键 .
- 一对多: 在多的表中添加建立关系的字段(外键) 指向另外一张表的主键 .
- 多对多: 需要创建一个单独的关系表,里面至少包含两个字段分别指向另外两个表的主键.
关联查询
- 同时查询多张表数据的查询方式称为关联查询
- 关联查询包括: 等值链接, 内连接和外连接
关联查询之等值链接
- 格式: select * from A,B where 关联关系
- 查询工资高于2000的员工姓名和对应的部门名
select e.name,d.name,sal
from emp e,dept d where e.dept_id=d.id and sal>2000;
关联查询之内连接
- 格式: select * from A join B on 关联关系
- 查询工资高于2000的员工姓名和对应的部门名
select e.name,d.name,sal from emp e join dept d on e.dept_id=d.id where sal>2000;
关联查询之外连接
- 等值链接和内连接查询到的都是两张表的交集数据
- 外连接查询的是一张表的全部和另外一张表的交集数据
- 格式: select * from A left/right join B on 关联关系
insert into emp(name,sal) values("灭霸",5);
1、查询所有员工姓名和对应的部门名
select e.name,d.name from emp e left join dept d on e.dept_id=d.id;
2、查询所有部门的名称,地点和对应的员工姓名和工资
select d.name,loc,e.name,sal
from emp e right join dept d on e.dept_id=d.id;
关联查询总结:
1、如果需要同时查询多张表的数据使用关联查询
2、关联查询包括:等值链接,内连接和外连接
3、等值链接和内连接查询的是两个表的交集数据, 推荐使用内连接
4、如果需要查询一张表的全部和另外一张表的交集时 使用外连接,只需要掌握左外即可,因为表的位置可以交换
如何查询多对多表中的数据
- 创建表:
create table student(id int primary key auto_increment,name varchar(50))charset=utf8;
create table teacher(id int primary key auto_increment,name varchar(50))charset=utf8;
create table t_s(tid int,sid int);
- 插入数据
insert into teacher values(null,"苍老师"),(null,"传奇哥");
insert into student values(null,"小明"),(null,"小红"),(null,"小绿"),(null,"小狗"),(null,"小黄");
insert into t_s values(1,1),(1,5),(1,4),(2,2),(2,3),(2,1),(2,5);
1、查询每个老师对应的学生
select t.name,s.name
from teacher t join t_s ts on t.id=ts.tid
join student s on s.id=ts.sid;
2、查询苍老师的学生都有谁?
select s.name
from teacher t join t_s ts on t.id=ts.tid
join student s on s.id=ts.sid
where t.name="苍老师";
3、查询小明的老师是谁?
select t.name
from teacher t join t_s ts on t.id=ts.tid
join student s on s.id=ts.sid
where s.name="小明";
JDBC
- JavaDataBaseConnectivity: Java数据库链接
- 学习JDBC主要学习的就是如何通过Java语言和MySQL数据库进行链接并执行SQL语句.
- JDBC是Sun公司提供的一套专门用于Java语言和数据库进行链接的API(Application Programma Interface应用程序编程接口)
- 为什么使用JDBC?
Sun公司为了避免Java程序员,每一种数据库软件都学习一套全新的方法,通过JDBC接口将方法名定义好, 让各个数据库厂商根据此接口中的方法名写各自的实现类(就是一个jar文件, 称为数据库的驱动) ,这样Java程序员只需要掌握JDBC接口中方法的调用,即可访问任何数据库软件.
如何通过JDBC链接数据库并执行SQL语句
- 创建Maven工程
- 在工程的pom.xml文件中 添加MySQL驱动的依赖坐标
- 创建cn.tedu.Demo01.java文件 添加以下代码
public class Demo01 {public static void main(String[] args) throws SQLException {//1.创建连接对象Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root");System.out.println("链接对象:"+conn);//2.创建执行SQL语句的对象Statement s = conn.createStatement();//3.执行SQL语句s.execute("create table jdbct1(age int)");//4.关闭资源conn.close();System.out.println("执行完成");}
}
执行SQL语句的对象Statement:
- execute("sql"); 此方法可以执行任意SQL语句, 但建议执行DDL(数据库相关和表相关的SQL语句)
- int row = executeUpdate("sql"); 此方法用来执行增删改相关的SQL语句, 返回值表示生效的行数
- ResultSet rs = executeQuery("sql"); 此方法用来执行查询相关的SQL语句,返回值ResultSet叫做结果集对象,查询到的数据都装在此对象中
实例1:
public class Demo03 {public static void main(String[] args) throws SQLException {Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false","root","root");Statement s = conn.createStatement();//执行插入数据SQL
// s.executeUpdate("insert into emp(name) values('tom')");//执行修改的SQL
// s.executeUpdate("update emp set name='jerry' where name='tom'");//执行删除的SQL
// s.executeUpdate("delete from emp where name='jerry'");//执行查询的SQLResultSet rs = s.executeQuery("select name,sal from emp");//遍历结果集中的数据while(rs.next()){//获取游标指向的这条数据的某个字段的值,通过字段名获取
// String name = rs.getString("name");
// double sal = rs.getDouble("sal");//通过查询回来数据的位置获取数据String name = rs.getString(1);double sal = rs.getDouble(2);System.out.println(name+":"+sal);}System.out.println("执行完成!");conn.close();}
}
实例2:
将创建连接对象封装起来
public class DBUtils {public static Connection getConn() throws SQLException {Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false","root","root");return conn;}
}
应用1:
public class Demo04 {public static void main(String[] args) {//从工具类中获取链接对象try (Connection conn = DBUtils.getConn()){//创建执行SQL语句的对象Statement s = conn.createStatement();//执行查询ResultSet rs = s.executeQuery("select name from emp");while(rs.next()){String name = rs.getString(1);System.out.println(name);}} catch (SQLException throwables) {throwables.printStackTrace();}}
}
应用2:
public class Demo05 {//添加main 方法 方法中创建一个hero表 有id,name,money价格 id自增//需要用上DBUtils工具类public static void main(String[] args) {try (Connection conn = DBUtils.getConn()){Statement s = conn.createStatement();s.execute("create table hero" +"(id int primary key auto_increment,name varchar(50),money int)");System.out.println("执行完成!");} catch (SQLException throwables) {throwables.printStackTrace();}}
}
应用3:
注意字符串的连接问题:
public class Demo6 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入英雄名");String name = sc.nextLine();System.out.println("请输入价格");int money = sc.nextInt();//获取数据库连接try (Connection conn = DBUtils.getConn()){Statement s = conn.createStatement();//字符串连接,字符串类型加单引号,int类型sql语句中没有单引号,所以在这里也不加.s.executeUpdate("insert into hero values(null,'"+name+"',"+money+")");System.out.println("执行完成");} catch (SQLException throwables) {throwables.printStackTrace();}}
}
应用4:
public class Demo07 {public static void main(String[] args) {{try (Connection conn = DBUtils.getConn()){Statement s = conn.createStatement();ResultSet rs =s.executeQuery("select *from hero");while(rs.next()){int id = rs.getInt(1);String name = rs.getString(2);double money = rs.getDouble(3);System.out.println(id+":"+name+":"+money);}System.out.println("执行完成");} catch (SQLException throwables) {throwables.printStackTrace();}}}
}
数据库连接池DBCP
- DataBaseConnectionPool, 数据库连接池
- 作用: 将连接重用,从而提高执行效率
如何使用数据库连接池?
public class Demo08 {public static void main(String[] args) throws SQLException {//创建连接池对象DruidDataSource ds = new DruidDataSource();//设置数据库连接信息 url 用户名 密码ds.setUrl("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false");ds.setUsername("root");ds.setPassword("root");//设置初始连接数量ds.setInitialSize(3);//设置最大连接数量ds.setMaxActive(5);//从连接池中获取连接 异常抛出Connection conn = ds.getConnection();System.out.println("连接对象:"+conn);}
}
将数据库连接池封装:
public class DBUtils {private static DruidDataSource ds;static{//创建连接池对象ds = new DruidDataSource();//设置数据库连接信息 url 用户名 密码ds.setUrl("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false");ds.setUsername("root");ds.setPassword("root");//设置初始连接数量ds.setInitialSize(3);//设置最大连接数量ds.setMaxActive(5);}public static Connection getConn() throws SQLException {//从连接池中获取连接 异常抛出Connection conn = ds.getConnection();System.out.println("连接对象:"+conn);return conn;}
}
注册登录
- 创建用户表
use empdb;
create table user(id int primary key auto_increment,username varchar(50),password varchar(50),nick varchar(50))charset=utf8;
select count(*) from user where username='tom' and password='123456';
- SQL注入: 往本应该传值的地方,传递进来的SQL语句,导致原有SQL语句的逻辑发生改变, 这个过程称为SQL注入
select count(*) from user
where username='abcd' and password='' or '1'='1'
PreparedStatement预编译的SQL执行对象
- 此对象可以将编译SQL语句的时间点提前,提前后可以将SQL语句逻辑部分提前锁死, 用户输入的内容将不能影响原有SQL语句的逻辑部分,从而解决了SQL注入的问题
- 如果SQL语句中存在变量,则必须使用PreparedStatement,解决SQL注入问题, 而且可以提高开发效率(避免了拼接字符串)
- 如果SQL语句中没有变量,可以使用Statement或PreparedStatement
实例1:
注册用户
public class Demo09 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();System.out.println("请输入昵称");String nick = sc.nextLine();//try (Connection conn = DBUtils.getConn()){Statement s = conn.createStatement();//字符串连接,字符串类型加单引号,int类型sql语句中没有单引号,所以在这里也不加.s.executeUpdate("insert into user values(null,'"+username+"','"+password+"','"+nick+"')");System.out.println("执行完成");} catch (SQLException throwables) {throwables.printStackTrace();}}
}
实例2:
用户登录
public class Demo10 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();//try (Connection conn = DBUtils.getConn()){
// Statement s = conn.createStatement();
// ResultSet rs = s.executeQuery("select count(*) from user where username='"
// +username+"' and password='"+password+"'");//通过PreparedStatement解决SQL注入问题String sql = "select count(*) from user where username=? and password=?";//编译SQL语句的时间点从之前执行时,提前到了创建对象时, 好处是此时编译用户输入的内容//还不在SQL语句里面,只是将原有SQL语句进行编译, 此时可以将原有SQL语句的逻辑部分锁死PreparedStatement ps = conn.prepareStatement(sql);//把?替换成变量 1和2代表的是?的位置 此时替换时只能以值的形式添加到原有SQL语句中,因为//逻辑部分已经编译好 已经锁死,这样用户输入的内容则不会影响原有SQL语句的逻辑。ps.setString(1,username);ps.setString(2,password);ResultSet rs = ps.executeQuery();//游标往下移动 指向查询回来的数据rs.next();//从结果集对象中取出此时游标指向的数据int count = rs.getInt(1);if (count>0){System.out.println("登录成功!");}else{System.out.println("用户名或密码错误");}} catch (SQLException throwables) {throwables.printStackTrace();}}
}
实例3:
用户登录 : 分别显示密码错误和用户登录错误
public class Demo11 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();try (Connection conn = DBUtils.getConn()){String sql = "select password from user where username=?";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1,username);//执行查询ResultSet rs = ps.executeQuery();//判断是否有数据if(rs.next()){//得到查询到的密码String pw = rs.getString(1);//拿用户输入的密码和查询到的密码进行比较if(pw.equals(password)){System.out.println("登录成功!");}else{System.out.println("密码错误");}}else{System.out.println("用户名不存在!");}} catch (SQLException throwables) {throwables.printStackTrace();}}
}
实例4:
实现注册功能 并实现用户名不能重复的功能
public class Demo12 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();System.out.println("请输入昵称");String nick = sc.nextLine();try (Connection conn = DBUtils.getConn()){// 使用PreparedStatement 实现注册功能 并实现用户名不能重复的功能//1.查询用户名是否存在String sql = "select id from user where username=?";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1,username);ResultSet rs = ps.executeQuery();if (rs.next()){System.out.println("用户名已存在!");return;}//2. 实现往user表中添加数据String insertSql = "insert into user values(null,?,?,?)";PreparedStatement insertPs = conn.prepareStatement(insertSql);insertPs.setString(1,username);insertPs.setString(2,password);insertPs.setString(3,nick);//执行插入insertPs.executeUpdate();System.out.println("注册完成!");}catch (SQLException throwables) {throwables.printStackTrace();}}
}
SpringBoot
Web服务软件做了那些事儿?
- web服务软件就是传奇老师带着写的webServer, 也就是Tomcat
- 负责建立底层的网络连接
- 根据客户端请求的静态资源路径找到对应的静态资源文件并把该文件返回给客户端
举例:http://localhost:8080/index.html
- 根据客户端请求的动态资源路径找到对应的Controller里面的方法并且执行
举例:http://localhost:8080/hello
- Web服务软件自身不提供任何业务功能,通过Controller给工程添加具体的业务功能
SSM三大框架
- Spring框架(第四阶段讲)
- SpringMVC框架(第二阶段到第四阶段)
- Mybatis框架(第三阶段到第四阶段)
SpringBoot框架
如果创建一个空工程,在此工程中使用SSM框架时需要添加大量的依赖和书写大量的配置文件, 通过SpringBoot框架可以更加便捷的让工程中引入各种框架, SpringBoot框架帮助我们构建工程.
如何创建SpringBoot工程
1、第一个页面中可以修改创建工程的网址
- https://start.spring.io 默认
- https://start.springboot.io 备用1
- https://start.aliyun.com 备用2
2、设置 以下内容
3、选择创建工程时添加的依赖
4、点击Finishi等待下载内容
5、如何检查工程是否创建成功?
在idea的底部 找到Build 然后看里面是否出现绿色的对勾
6、如果第五步没有绿色对勾 , 刷新maven
7、检查maven是否已经改成aliyun的配置文件
8、如果已经改成aliyun的 还有错的话, 找到.m2文件夹下的repository文件夹删除 ,删除完之后再次重复第6步 刷新maven
9、在工程的static文件夹中添加index.html 页面中显示HelloSpringBoot 启动工程 通过浏览器访问http://localhost:8080 检查是否显示了此页面
10、创建controller.HelloController类 在里面添加hello方法处理/hello请求,给客户端响应一句话, 重启工程,浏览器访问http://localhost:8080/hello 测试是否成功
SpringBoot常见错误列表:
1、浏览器中显示404状态码
404代表找不到资源
找不到静态资源: 比如 *.html *.jpg *.xxx
- 检查浏览器请求路径是否正确
- 检查文件是否保存在了正确的位置(一般放在static文件夹下面)
- 如果上面两种情况都没有问题,重新编译工程并重启工程 Build->ReBuild
找不到动态资源: 比如 /hello 由controller处理的路径称为动态资源
- 检查浏览器请求路径是否正确
- 检查Controller是否创建在了工程自带的包的里面
- 检查是否在Controller类里面的类名上面添加@Controller注解
- 检查Controller里面RequestMapping注解中处理的路径是否正确
- 如果上面两种情况都没有问题,重新编译工程并重启工程 Build->ReBuild
2、浏览器显示500状态码
500代表服务器执行错误, 此时第一时间查看idea控制台的错误,里面会有错误相关的提示,根据提示信息再分析具体哪里错了.
表设计面试题
2021年过年时小明在这些天都收到了许多亲戚\朋友还有同事的红包,也发出了一些红包,有的是微信,有的是支付宝也有现金,请参考下面的题目帮小明设计表格保存红包的信息
(至少包含一张流水表) 先列出需要保存的数据有哪几种
关系,红包类型,红包金额,时间,性别,名字
1.设计表
流水表: id,红包金额,时间,红包类型,人物id
create table trade(id int primary key auto_increment,money int,time date,type varchar(10),person_id int)charset=utf8;
人物表: id,名字,性别,关系
create table person(id int primary key auto_increment,name varchar(50),gender char(1),rel varchar(5))charset=utf8;
- 准备数据
- 插入人物数据: 人物表,刘德华 男 亲戚 ,杨幂 女 亲戚 ,马云 男 同事,特朗普 男 朋友, 貂蝉 女 朋友
insert into person values(null,'刘德华','男','亲戚'),(null,'杨幂','女','亲戚'),(null,'马云','男','同事'),(null,'特朗普','男','朋友'),(null,'貂蝉','女','朋友');
- 插入流水数据:
刘德华 微信 收1000 2021-03-20
杨幂 现金 收500 发50 2021-04-14
马云 支付宝 收20000 发5 2021-03-11
特朗普 微信 收2000 2021-05-18
貂蝉 微信 发20000 2021-07-22
insert into trade values(null,1000,"2021-03-20","微信",1),
(null,500,"2021-04-14","现金",2),(null,-50,"2021-04-14","现金",2),
(null,20000,"2021-03-11","支付宝",3),(null,-5,"2021-03-11","支付宝",3),(null,2000,"2021-05-18","微信",4),
(null,-20000,"2021-07-22","微信",5);
2. 统计2021年2月15号到现在的所有红包收益
select sum(money) from trade where time>"2021-2-15";
3. 查询2021年2月15号到现在 金额大于100 所有女性亲戚的名字和金额
select name,money from person p join trade t on p.id=t.person_id where time>"2021-2-15" and money not between -100 and 100 and gender="女" and rel="亲戚";
4. 查询三个平台(微信,支付宝,现金)分别收入的红包金额
select type,sum(money) from trade where money>0 group by type;
客户端发出请求的几种方式
1、通过浏览器的地址栏中发出请求
2、通过html页面中的超链接发出请求
3、通过html页面中的form表单发出请求
4、通过前端框架发出请求
工程中使用数据库需要做的几件事:
首先:创建一个SpringBoot工程
1、在pom.xml中添加 MySQL依赖和数据库连接池依赖,从jdbc01工程中去复制两个依赖粘贴到新工程中, 然后刷新maven(必须做)
2、把jdbc01工程中的DBUtils 复制到新工程的utils包下面
<!-- 连接MySQL数据库的依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.21</version></dependency>
//数据库的工具类
public class DBUtils {private static DruidDataSource ds;static {//创建连接池对象ds = new DruidDataSource();//设置数据库连接信息 url 用户名 密码ds.setUrl("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai");ds.setUsername("root");ds.setPassword("root");//设置初始连接数量ds.setInitialSize(3);//设置最大连接数量ds.setMaxActive(5);}public static Connection getConn() throws SQLException {//从连接池中获取连接 异常抛出Connection conn = ds.getConnection();return conn;}
}
Mybatis框架
此框架是目前最流行的数据持久层框架,是对JDBC代码进行了封装, 程序员只需要通过注解或配置文件的方式提供需要执行的SQL语句,框架会自动根据SQL语句生成出JDBC代码,从而提高执行效率.
如何使用Mybatis框架?
1..创建boot2-2工程 , 创建工程时需要勾选3个内容分别是:
Web->Spring Web
SQL-> Mybatis Framework
SQL-> MySQL Driver
2..在application.properties配置文件中书写连接数据库的信息
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
Mybatis框架添加英雄步骤:
1、创建boot2-3 打钩 3个
2、在application.properties配置文件中添加内容
3、停止之前工程, 运行新工程测试是否能正常运行
4、创建index.html 页面 里面添加超链接 添加英雄 访问地址为add.html
5、创建add.html页面 里面添加form表单 请求地址为 /add
6、创建controller.HeroController, 里面添加@Controller注解,添加@RequestMapping注解处理 /add请求 并添加add方法,
7、创建entity.Hero实体类 并提供get和set方法 还有tostring方法
8、在HeroController的add方法参数列表中声明Hero对象 用来接收传递过来的参数 ,此时打桩输出hero对象 检查是否接收到了参数
9、创建mapper.HeroMapper接口, 里面添加@Mapper注解, 声明一个insert方法通过@Insert注解修饰,注解里面添加插入数据的SQL语句
10、在HeroController里面 通过@Autowired注解把HeroMapper装配进来, 在add方法里面调用mapper.insert方法把接收到的hero对象传递进去, 重启工程测试即可!
删除英雄步骤:
1、在首页中添加删除英雄超链接 访问地址为 delete.html
2、创建delete.html页面 在里面添加form表单 提交地址为/delete
3、在HeroController 中创建delete方法 处理路径为/delete 参数列表中声明name 接收页面传递过来的名字
4、在HeroMapper里面添加deleteByName方法 通过@Delete注解修饰,里面填写 删除的SQL语句
5、在HeroController里面的delete方法中调用mapper的deleteByName方法
修改英雄步骤:
1、在首页添加修改英雄超链接, 地址为update.html页面
2、创建update.html页面 并添加form表单 提交地址为/update
3、在Controller中添加update方法 处理/update请求
4、在HeroMapper里面添加update方法 通过@Update注解进行修饰,里面添加修改的SQL语句
5、在HeroController里面的update方法中调用mapper的update方法把接收到的hero对象传递到方法中
查询英雄步骤:
1、在首页添加查询的超链接,请求地址为/select
2、在HeroController中添加select方法处理/select请求
3、在HeroMapper里面添加select方法用@Select注解进行修饰,里面写查询的SQL语句
4、在HeroController的select方法中 调用mapper的select方法,把查询到的List集合返回给客户端展示
实例1:(传参的几种方式)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>工程首页</h1>
<h2>通过超链接发出请求</h2>
<!--localhost:8080/hello-->
<!--相对路径:相对于当前页面所处位置-->
<a href="hello">相对路径</a>
<!--******绝对路径1: 相对于工程的根路径 /代表工程根路径http://localhost:8080/-->
<a href="/hello">绝对路径1</a>
<!--绝对路径2,这种写法一般访问其它网站资源时使用-->
<a href="http://localhost:8080/hello">绝对路径2</a>
<h2>通过from表单发出请求</h2>
<form action="/param1"><input type="text" name="info"><input type="submit">
</form>
<h2>第二种传参方式</h2>
<form action="/param2"><input type="text" name="name"><input type="text" name="age"><input type="submit">
</form>
<h3>第三种方式</h3>
<form action="/param3"><input type="text" name="name"><input type="text" name="sal"><input type="text" name="job"><input type="submit">
</form>
</body>
</html>
@Controller
public class HelloController {
// @RequestMapping("/hello")
// public void hello(HttpServletResponse response) throws IOException {
// response.setContentType("text/html;charset=utf-8");
// PrintWriter pw = response.getWriter();
// pw.print("测试成功");
// pw.close();
// }@RequestMapping("/hello")@ResponseBody //SpringMVC框架提供的注解,作用:可以通过返回值的方式给客户端响应数据public String hello(){return "测试成功2";}@RequestMapping("/param1")@ResponseBodypublic String param1(HttpServletRequest request){String info = request.getParameter("info");return "接受到了参数:"+info;}@RequestMapping("/param2")@ResponseBodypublic String param2(String name,int age){return "接受到了参数:"+name+"年龄:"+age;}@RequestMapping("/param3")@ResponseBodypublic String param3(Emp emp){return emp.toString();}
}
下面是还需要自己手写JDBC语句的例子:(Springboot框架下)
@Controller
public class UserController {@RequestMapping("/reg")@ResponseBodypublic String reg(User user){//得到数据库连接try (Connection conn = DBUtils.getConn()){//参考昨天jdbc01里面的Demo12String sql = "select id from user where username=?";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1,user.getUsername());ResultSet rs = ps.executeQuery();if (rs.next()){return "用户名已存在!";}String insertSql = "insert into user values(null,?,?,?)";PreparedStatement insertPs = conn.prepareStatement(insertSql);insertPs.setString(1,user.getUsername());insertPs.setString(2,user.getPassword());insertPs.setString(3,user.getNick());insertPs.executeUpdate();} catch (SQLException throwables) {throwables.printStackTrace();}return "注册成功!";}@RequestMapping("/login")@ResponseBodypublic String login(User user){System.out.println("user = " + user);//soutptry (Connection conn = DBUtils.getConn()){String sql = "select password from user where username=?";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1,user.getUsername());ResultSet rs = ps.executeQuery();if (rs.next()){//代表查询到了信息//判断用户输入的和查询到的数据是否一致if (rs.getString(1).equals(user.getPassword())){return "登录成功!";}return "密码错误!";}} catch (SQLException throwables) {throwables.printStackTrace();}return "用户名不存在!";}
}
下面是不需要自己手写JDBC语句的例子:(添加了Mybatis框架下)
@Mapper
public interface HeroMapper {//#{xxx}会从下面方法的参数列表中找到同名变量//如果找不到就会进入Hero实体类中找到同名的get方法获取值//Mybatis框架会根据此方法声明生成具体的实现类,方法内部就是JDBC代码@Insert("insert into hero values(null,#{name},#{money})")void insert(Hero hero);@Delete("delete from hero where name=#{name}")void deleteByName(String name);@Update("update hero set name=#{name},money=#{money} where id=#{id}")void update(Hero hero);@Select("select *from hero")List<Hero> select();}
@Controller
public class HeroController {//自动装配注解的作用: Spring框架结合Mybatis框架会自动将HeroMapper生成一个实现类和实现里面的方法//而且会自动实例化该对象 required = false告诉idea编译器此对象是非必须的@AutowiredHeroMapper mapper; //框架自动创建了HeroMapper接口的实现类,并创建了实现类对象,此对象就是mapper.@RequestMapping("/add")@ResponseBodypublic String add(Hero hero){System.out.println("hero = "+hero);mapper.insert(hero);//此方法相当于之前执行的JDBC代码return "添加完成!";}@RequestMapping("/delete")@ResponseBodypublic String delete(String name){//调用mapper里面的删除方法mapper.deleteByName(name);return "删除完成";}@RequestMapping("/update")@ResponseBodypublic String update(Hero hero){System.out.println("hero = "+hero);mapper.update(hero);return "修改完成";}@RequestMapping("/select")@ResponseBodypublic String select(){List<Hero> list = mapper.select();return list.toString();}}
商品表的增删改查
创建商品表
use empdb;
create table product(id int primary key auto_increment,title varchar(100),price double(10,2),sale_count int)charset=utf8;
1、创建boot3-1工程 打3个勾
2、从别的工程中复制application.properties配置文件的信息到新工程, 启动工程测试是否成功.
同步请求和异步请求
- 同步: 指单线程依次做几件事
- 异步: 指多线程同时做几件事
- 同步请求: 指客户端浏览器只有一个主线程, 此线程负责页面的渲染和发出请求等操作, 如果此主线程发出请求的话则停止渲染而且会清空页面显示的内容 直到服务器响应了数据后才能再次显示, 由于主线程清空了原有显示的内容所以只能实现页面的整体刷新(整体改变)
- 异步请求: 指客户端的主线程只负责页面渲染相关操作,发请求的事儿由新的子线程操作, 这样子线程发出请求时页面不需要清空,而且可以将查询回来的数据展示在原有页面基础之上, 这样实现的效果就叫做页面的局部刷新
客户端发出请求的几种方式
1、通过浏览器的地址栏中发出请求 同步请求
2、通过html页面中的超链接发出请求 同步请求
3、通过html页面中的form表单发出请求 同步请求
4、通过前端框架发出请求 异步请求
客户端如何发出异步请求
1、通过Axios框架发出异步请求
2、此框架就是一个普通的js文件 页面需要使用此框架时需要将此文件引入到页面中
3、从苍老师文档服务器中找到axios框架地址
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
Get请求和Post请求
从字面意思理解, Get是跟服务器要数据, Post是给服务器传数据
1、Get: 请求参数写在请求地址的后面(可见),请求参数有大小限制只能穿几k的数据(不能处理文件上传)。
应用场景: 查询请求一般都会使用get, 删除也会使用get请求
2、Post:请求参数放在请求体里面(不可见),参数没有大小限制
应用场景: 文件上传, 带有敏感信息的请求(比如注册登录时有密码)
注册登录步骤:
1、创建工程boot3-2 打钩3个
2、从之前工程中复制application.properties里面的连接数据库的信息 ,复制完之后立即启动工程 测试是否创建成功, 如果工程启动不起来 检查报错是不是因为端口被占用, 如果不是 刷新maven 再次启动 ,如果还是启动不了 删除工程重新创建新工程 直至启动成功.
3、创建index.html页面 在里面添加两个超链接访问注册和登录页面
4、创建reg.html页面 在页面中引入vue和axios两个框架文件 从之前工程中复制js文件夹(检查里面是不是包含这两个框架文件) 在页面中 点击按钮时向/reg发出异步请求,同时把用户输入的信息提交给服务器,然后在then方法里面判断返回的response.data值为1代表注册成功 显示首页 值为2代表用户名已存在
5、创建controller.UserController 并且创建entity.User实体类
6、在Controller里面添加reg方法处理/reg请求 声明User变量用来接收传递过来的用户信息
7、创建mapper.UserMapper 在里面提供两个方法 分别是 selectByUsername 和 insert两个方法
8、回到Controller里面把UserMapper通过@Autowired装配进来,在reg方法中先调用mapper里面的selectByUsername方法 判断返回值是否有值 如果有值则给客户端返回2代表用户名已存在 如果没有值 则调用mapper的insert方法 把用户信息保存到数据库,最后返回1 代表注册成功
9、下一步开始实现登录功能, 步骤类似注册 先创建login.html页面 然后在页面中通过Vue对内容进行管理 当点击登录按钮的时候 向/login发出异步请求 同样把输入的用户信息提交给服务器, 在then方法中判断response.data的值为1代表登录成功显示首页 值为2 代表用户名不存在, 值为3 代表密码错误
10、在Controller里面添加login方法处理/login请求,声明User对象接收传递过来的用户信息, 在方法中调用mapper的selectByUsername 通过用户输入的用户名查询对应的用户信息,如果没有查询到 直接返回2代表用户名不存在,如果查询到了 继续通过输入的密码和查询到的密码比较如果一致返回1代表登录成功, 如果不一致返回2 代表密码错误.
boot3-1实例:
product表格的定义:(注意这里是sale_count)
Product类的创建:(这里是saleCount)
index页面:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>商品管理首页</h1>
<a href="/insert.html">添加商品</a>
<a href="/select">查询商品</a>
<a href="/update.html">修改商品</a>
<hr>
<a href="/helloAxios.html">异步请求测试</a>
</body>
</html>
同步请求:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>添加商品页面</h1>
<form action="/insert"><input type="text" name="title" placeholder="商品标题"><input type="text" name="price" placeholder="商品价格"><input type="text" name="saleCount" placeholder="商品销量"><input type="submit" value="添加">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>修改商品页面</h1>
<form action="/update"><input type="text" name="id" placeholder="请输入修改商品的id"><input type="text" name="title" placeholder="商品标题"><input type="text" name="price" placeholder="商品价格"><input type="text" name="saleCount" placeholder="商品销量"><input type="submit" value="修改">
</form>
</body>
</html>
异步请求:(这里是div块)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div><h1>{{info}}</h1><input type="button" value="测试异步请求get" @click="f1()"><input type="button" value="测试异步请求post" @click="f2()">
</div>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<script>let v = new Vue({el:"div",data:{info:"测试vue"},methods:{f1(){// alert("xxx");//发出异步请求axios.get("/hello1Axios?info=tom").then(function (response) {//response代表服务器响应对象//response.data代表服务响应的数据alert(response.data);})},f2(){//发出异步post请求axios.post("/hello2Axios",{info: "刘德华"}).then(function (response) {alert(response.data);})}}})
</script>
</body>
</html>
ProductMapper接口:
@Mapper
public interface ProductMapper {
// insert into product values(null,‘手机’,500,100);@Insert("insert into product values(null,#{title},#{price},#{saleCount})")void insert(Product product);@Select("select * from product")@Result(column = "sale_count",property = "saleCount")List<Product> select();@Delete("delete from product where id=#{id}")void deleteById(int id);@Update("update product set title=#{title},price=#{price}" +",sale_count=#{saleCount} where id=#{id}")void update(Product product);}
ProductController类:(处理同步请求)
//此注解相当于在每一个方法上面添加ResponseBody注解
@RestController
public class ProductController {@Autowired(required = false)ProductMapper mapper;@RequestMapping("/insert")public String insert(Product product){System.out.println("product = " + product);mapper.insert(product);return "添加完成!<a href='/'>返回首页</a>";}@RequestMapping("/select")public String select(){List<Product> list = mapper.select();String html = "<table border=1>";html+="<caption>商品列表</caption>";html+="<tr><th>id</th><th>标题</th><th>价格</th><th>销量</th><th>操作</th></tr>";//把商品数据装进表格标签里面for (Product p: list) {html+="<tr>";html+="<td>"+p.getId()+"</td>";html+="<td>"+p.getTitle()+"</td>";html+="<td>"+p.getPrice()+"</td>";html+="<td>"+p.getSaleCount()+"</td>";html+="<td><a href='/delete?id="+p.getId()+"'>删除</a></td>";html+="</tr>";}html+="</table>";return html;}@RequestMapping("/delete")public String delete(int id){System.out.println("id = " + id);mapper.deleteById(id);return "删除完成!<a href='/select'>返回列表页面</a>";}@RequestMapping("/update")public String update(Product product){System.out.println("product = " + product);mapper.update(product);return "修改完成!<a href='/select'>返回列表页面</a>";}
}
AxiosController类:(处理异步请求)
@RestController
public class AxiosController {@RequestMapping("/hello1Axios")public String hello1(String info){return "请求成功! info="+info;}//@RequestBody注解作用, 当客户端发出post请求并且提交的是自定义对象时 服务器端//接收参数必须使用此注解 否则得不到传递过来的参数.@RequestMapping("/hello2Axios")public String hello2(@RequestBody String info){return "请求成功! info="+info;}}
数据库和SpringBoot基础01相关推荐
- 【SQL数据库基础01】数据库和SQL概述
文章目录 01 引入 1.1 数据库存储数据的特点 1.2 三个重要概念 1.2.1 DBMS 1.3 SQL的优点: 图例说明: 1.4 SQL语言四大类 1.4.1 数据查询语言DQL 1.4.1 ...
- SpringBoot基础入门 01
一.SpringBoot基础 1.1 原有Spring优缺点分析 1.1.1 Spring的优点分析 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE ...
- SpringBoot基础重难点
来源:SpringBoot基础重难点 - liangxiaolong - 博客园 1.SpringBoot 1.1 概念 Spring Boot是构建所有基于Spring的应用程序的起点.Spring ...
- 【重难点】【Java基础 01】一致性哈希算法、sleep() 和wait() 的区别、强软弱虚引用
[重难点][Java基础 01]一致性哈希算法.sleep() 和wait() 的区别.强软弱虚引用 文章目录 [重难点][Java基础 01]一致性哈希算法.sleep() 和wait() 的区别. ...
- 【Java笔记+踩坑】SpringBoot基础3——开发。热部署+配置高级+整合NoSQL/缓存/任务/邮件/监控
导航: [黑马Java笔记+踩坑汇总]JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud/SpringCloudAlibaba+黑马旅游+谷粒商城 目录 ...
- SpringBoot基础知识
SpringBoot基础知识 SpringBoot课程笔记 前言 很荣幸有机会能以这样的形式和互联网上的各位小伙伴一起学习交流技术课程,这次给大家带来的是Spring家族中比较重要的一门技术课程- ...
- 8. SpringBoot基础学习笔记
SpringBoot基础学习笔记 课程前置知识说明 1 SpringBoot基础篇 1.1 快速上手SpringBoot SpringBoot入门程序制作 1.2 SpringBoot简介 1.2.1 ...
- SpringBoot基础的依赖说明
SpringBoot基础的依赖说明 前言 前提 spring-boot-starter-parent spring-boot-starter-web spring-boot-configuration ...
- 动力节点王鹤SpringBoot3学习笔记——第二章 掌握SpringBoot基础篇
目录 二.掌控SpringBoot基础篇 2.1 Spring Boot ? 2.1.1 与Spring关系 2.1.2 与SpringCloud关系 2.1.3 最新的Spring Boot3 新 ...
最新文章
- cuda 核函数 for循环_【CUDA 基础】6.2 并发内核执行
- python布尔类型运算_Python中布尔类型
- mysql数据库持续_MySql数据库--持续记录ing
- android 分享元素,Android开发之5.0activity跳转时共享元素的使用方法
- kotlin 添加第一个 集合_kotlin 集合的操作
- c语言报刊杂志订阅系统,中国报刊杂志大全_报刊大全_报刊杂志订阅
- [转]架构师的职责及工作描述
- EDI 公开课:EDI 系统集成之数据库方案
- 基于51单片机ADC0808自动数字电压表仿真数码管显示
- zip 和rar 的区别
- google 安装去广告插件
- Android基于Facebook Rebound的动画效果框架Backboard demo (非常炫酷)
- 11月20日云栖精选夜读:围观阿里总部:边喝茶边搞技术是一种怎样的体验?
- 【翻译】我们为什么要关注AIOps?
- [转]android 制作.9.png图片 解决图形变形问题
- 李想:从放弃高考到如今第三次创业,我的经验和教训
- (附源码)springboot曦乐苹果园林管理系统的设计与实现 毕业设计100854
- 用计算机处理信息的过程,计算机处理信息的全过程
- 一个运动控制系统的实例
- “大湾区杯”金融数学建模赛后闲谈
热门文章
- WPF Multi-Touch 开发:基础触屏操作(Raw Touch)
- C语言getchar的用法详解
- 升讯威微信营销系统开发实践:(1)功能概要与架构设计( 完整开源于 Github)...
- http相关知识 - (2)状态管理 - session
- SAP 采购订单入库——最近收货日期
- linux暂停一个在运行中的进程
- 线程队列,线程池,协程
- vue 鼠标点击特效动画(css3动画),水波纹动画效果
- down 网卡端口周期性的up_down 网卡端口周期性的up_端口每隔一段时间就就会不停up/down,是端口硬件故障了吗?......
- PHP+Mysql—白酒管理系统(前端+后端)