- 分组查询可以将某个字段相同的值划分为一组, 然后以组为单位进行统计查询
- 需求中如果出现 每个xxx或每种xxx 一般都使用分组查询, 并以xxx作为分组的字段
1. 查询每个部门的平均工资
select dept_id,avg(sal) from emp group by dept_id;
2. 查询1号和2号部门的人数
select dept_id,count(*) from emp where dept_id in(1,2) group by dept_id;
- where后面只能写普通字段的条件, 不能写聚合函数的条件
- having后面写聚合函数条件, 需要和group by结合使用 ,写在group by的后面
1. 查询每种工作的人数,只查询人数大于1的工作名称和人数.
select job,count(*) from emp group by job having count(*)>1;
- 别名写法:
select job,count(*) c from emp group by job having c>1;
2. 查询每个部门的平均工资,只查询工资在1000到3000之间的,并且过滤掉平均工资低于2000的部门信息
select dept_id,avg(sal) a from emp where sal between 1000 and 3000 group by dept_id having a>=2000;
- 可以将一条SQL语句的查询结果当成另外一条SQL语句条件的值
1. 查询工资高于1号部门平均工资的员工信息
select avg(sal) from emp where dept_id=1;
select * from emp where sal>(select avg(sal) from emp where dept_id=1);
2. 查询拿最低工资员工的同事们的信息(同事指相同部门)
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 关联关系 and 其它条件;
查询程序员的名字,工资,部门名和部门地点
select e.name,e.sal,d.name,d.loc
from emp e,dept d
where e.dept_id=d.id and job='程序员';
- 等值连接和内连接查询到的数据是一样的,查询的是两个表的交集数据
- 格式: select * from A join B on 关联关系 where 其它条件
查询所有普通人的信息
select e.*
from emp e join dept d on e.dept_id=d.id
where d.name='普通人';
- 等值连接和内连接查询到得都是两个表得交集数据
- 通过外连接可以查询一张表得全部和另外一张表得交集
- 格式: select * from A left/right join B on 关联关系 where 其它条件;
查询所有部门的名字和对应的员工姓名,工资和工作
select d.name,e.name,e.sal,e.job
from emp e right join dept d on e.dept_id=d.id;
- Java DataBase Connectivity, Java数据库连接
- 学习JDBC就是学习如何通过Java代码执行SQL语句
- JDBC是Sun公司提供的一套专门用于Java语言和数据库软件进行连接的API(Application Programma Interface)
- 为什么使用JDBC
如果没有JDBC接口, Java程序员有可能每一种数据库都需要学习一套新的方法,Sun为了避免Java程序员做无用功,通过JDBC接口规范了各个数据库厂商的方法名, 各个厂商必须遵循JDBC接口中定义好的方法写各自的实现类, 这样Java程序员只需要按照JDBC接口中方法名称去调用,写出的代码可以连接任何数据库软件.
- 如何使用JDBC连接数据库
- 创建maven工程
- 在pom.xml中添加MySQL驱动依赖
<dependencies> <!-- 连接MySQL数据库的依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency> </dependencies>
- 创建Demo01.java 在main方法中添加以下代码:
//1.获取连接对象 抛异常 Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&server Timezone=Asia/Shanghai", "root","root"); //2.创建执行SQL语句的对象 Statement s = conn.createStatement(); //3. 执行SQL语句 execute执行 s.execute("create table jdbct1(name varchar(20))"); //4. 关闭资源 conn.close(); System.out.println("执行完成!");
- execute(sql); 此方法可以执行任意SQL语句 但是推荐执行DDL
- executeUpdate(sql); 此方法执行增删改相关SQL语句
- ResultSet rs = executeQuery(sql); 此方法执行查询相关的SQL语句
- getString("name"); 通过查询表字段的名称获取数据
- getString(1); 通过查询表字段的位置获取数据
- DataBaseConnectionPool
- 数据库连接池可以将连接重用,避免频繁的开关连接导致的执行效率降低, 从而提高了执行效率
- 如何使用数据库连接池?
- 在pom.xml中添加连接池的依赖 并 刷新maven
<!-- 数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency>
- 用户在传值的地方传进了SQL语句的关键字,导致原有SQL语句的逻辑发生改变,这种过程称为SQL注入.
- ' or '1'='1
### PreparedStatement
- 带预编译功能的执行SQL语句的对象
- 如何解决的SQL注入问题?
在预编译SQL语句时,将SQL语句的业务逻辑锁死, 之后才把用户输入的内容以值的形式替换进去, 这样就不会影响原有SQL语句的业务逻辑, 从而解决了SQL注入问题.
- 什么时候使用PreparedStatement?
如果SQL语句中存在变量时必须使用PreparedStatement, 如果没有变量使用Statement或PreparedStatement都可以.
- 服务器就是一台高性能的电脑, 在这台电脑上安装了提供xxx服务的软件,就可以称为xxx服务器
- 举例:
- 邮件服务器: 在电脑上安装了提供邮件收发服务的软件.
- ftp服务器: 在电脑上安装了提供文件上传下载服务的软件
- 数据库服务器: 在电脑上安装了MySQL/Oracle...
- Web服务器: 在电脑上安装了Web服务软件(Tomcat)
1. 负责搭建底层的网络连接
2. 负责根据客户端请求的静态资源地址,找到对应的静态资源文件并返回给客户端.
3. 负责根据客户端请求的动态资源地址,找到对应的Servlet并实例化运行
- Web服务软件(Tomcat) 不具备任何的业务功能,Servlet是用于扩展Web服务软件业务功能的组件, Web服务软件可以理解为一个容器, 每一个业务都需要对应一个Servlet
- SpringMVC框架中出现的Controller, 这个Controller的作用是将多个有相关性的Servlet进行了整合(比如,RegServlet/LoginServlet/AllUserServlet/UpdateServlet/DeleteServlet 使用一个UserController可以将这多个Servlet合并成一个)
- SpringBoot是Spring公司提供的一个框架,作用是创建工程时能够非常便捷的引入其它常用框架.
- 为什么使用SpringBoot?
如果不使用SpringBoot, 从零开始创建一个空工程,在工程中每引入一个框架都需要做大量的配置工作以确保框架正常运行, 这样开发的过程中需要用到大量的框架,这样就需要做大量的配置工作, 非常占用时间而且容易出错,使用SpringBoot框架创建工程,可以非常便捷的引入其它框架,省去了大量的配置工作从而能够提高开发效率
1. 创建工程时选择Spring initalizr , 如果下一步时出现timeout 标示请求超时,换一个路径
https://start.springboot.io
. 下一步 选择Web->Spring Web 作用是引入Tomcat容器
. 下一步直到Finish
. 创建完工程后 检查 Build里面是否显示绿色对钩
. 如果创建完工程后在Build里面显示错误提示, 进入到maven面板点击刷新,如果问题没有解决删除.m2文件夹下的repository文件夹后 再来刷新,反复操作直到能成功.
- 任何客户端任何时间请求到的内容都是不变的内容称为静态资源
- 请求到的内容会根据不同的用户不同的时间得到不同的数据,这种属于动态资源
![image-20210831172611588](image-20210831172611588.png)
1. 检查是否是之前的工程没有停止导致,如果是先关闭之前工程即可 90%
2. 电脑上某个软件占用了8080端口, 修改工程的端口号, 找到工程的application.properties配置文件 添加以下内容: server.port=xxxx
3. 重启电脑也可以解决端口被占用
Java DataBase Connectivity: Java数据库连接, 学习JDBC主要学习的就是如何在Java代码中执行SQL语句
JDBC是Sun公司提供的一套通过Java连接数据库的API(Application Programma Interface 应用程序编程接口)
为什么使用JDBC
如果没有JDBC接口, 每个数据库厂商都有可能定义自己一套全新的方法(做的事儿是一样的但是方法名可能不一样),这样对于Java程序员而言需要学习几套不同的方法, 为了避免这种情况出现,Sun公司定义了JDBC接口,将方法名固定, 让各个数据库厂商根据此方法名写各自的实现类, 这样java程序员只需要遵循JDBC的标准写代码,就算将来换数据库,代码也不用变 ,因为各个数据库厂商提供的方法名是一样的.
1.创建maven工程
2.在pom.xml中添加mysql驱动的依赖(驱动实际上就是JDBC方法的实现类)
3.通过以下代码 连接数据库并执行SQL语句
//获取数据库连接 异常抛出 http:// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/newdb3?" +"characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root"); //root 密码 System.out.println(conn); //创建执行SQL语句的对象 Statement s = conn.createStatement(); //执行SQL语句 s.execute("create table jdbct1(id int)"); //关闭资源 conn.close();
<!-- 数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency>
相关代码
//创建数据库连接池对象 DruidDataSource dds = new DruidDataSource(); //设置数据库连接信息 dds.setUrl("jdbc:mysql://localhost:3306/newdb3?characterEncoding=utf8&" + "serverTimezone=Asia/Shanghai"); dds.setUsername("root"); dds.setPassword("root"); dds.setInitialSize(3);//设置初始连接数量 dds.setMaxActive(5);//设置最大连接数量 //从连接池中获取连接 异常抛出 Connection conn = dds.getConnection(); System.out.println(conn);
登录功能案例:
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(); //准备查询的SQL语句 把用户名和密码拼接进去 String sql = "select count(*) from user where username='" +username+"' and password='"+password+"'"; ResultSet rs = s.executeQuery(sql); //不管用户输入什么 都会有结果所以不用判断是否有下一条数据直接移动游标 rs.next(); //取出查询到的数量 int count = rs.getInt(1); if (count>0){ System.out.println("登录成功!"); }else{ System.out.println("用户名或密码错误!"); } } catch (SQLException throwables) { throwables.printStackTrace(); }
什么是SQL注入?
往SQL语句中添加值的地方,添加进去了SQL语句导致原有SQL语句的业务逻辑发生改变,这种行为称为SQL注入
// **********************解决SQL注入问题*************************** //用? 把变量的位置占上 String sql = "select count(*) from user " + "where username=? and password=?"; //创建执行SQL语句的对象 //预编译: 由原来执行时编译 提前到创建时编译,编译SQL语句时将SQL语句的 //业务逻辑锁死, 编译后不会被用户输入的内容所影响 PreparedStatement ps = conn.prepareStatement(sql); //替换SQL语句中的? ps.setString(1,username); ps.setString(2,password); //执行查询 ResultSet rs = ps.executeQuery();
作用: 可以将多条SQL语句进行的多次网络数据传输合并成一次传输,从而提高了执行的效率
Statement相关代码:
//批量操作 三次合并成一次数据传输 s.addBatch(sql1);//添加到批量操作 s.addBatch(sql2); s.addBatch(sql3); s.executeBatch();//执行批量操作