JavaWeb笔记02
三、数据库设计
1_简介
1.数据库设计设计什么?
有哪些表
表里有哪些字段
表和表之间是什么关系
2.表关系有哪几种?
一对一
一对多(多对一)
多对多
2_多表关系实现
表关系之一对多
一对多 (多对一):
如:部门表和员工表
一个部门对应多个员工,一个员工对应一个部门
实现方式:在多的一方建立外键,指向一的一方的主键
表关系之多对多
多对多:
如:订单和商品
一个商品对应多个订单,一个订单包含多个商品
实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
表关系之一对一
一对一:
如:用户和用户详情
一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能
实现方式:在任意一方加入外键,关联另一方主键,并且设置外键为唯一 (UNIQUE)
四、多表查询
1_简介
多表查询
笛卡尔积:取 A,B 集合所有组合情况
多表查询:从多张表查询数据
连接查询
内连接:相当于查询 A B 交集数据
外连接:
左外连接:相当于查询 A 表所有数据和交集部分数据
右外连接:相当于查询 B 表所有数据和交集部分数据
子查询
2_内连接&外连接
内连接
内连接查询语法
-- 隐式内连接
SELECT 字段列表 FROM 表1,表2... WHERE 条件;
-- 显式内连接
SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 条件;
内连接相当于查询 A B 交集数据
外连接
外连接查询语法
-- 左外连接
SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件;
-- 右外连接
SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件;
左外连接:相当于查询 A 表所有数据和交集部分数据
右外连接:相当于查询 B 表所有数据和交集部分数据
3_子查询
子查询
1.子查询概念:
查询中嵌套查询,称嵌套查询为子查询
2.子查询根据查询结果不同,作用不同:
单行单列
多行单列
多行多列
单行单列:作为条件值,使用 = != > < 等进行条件判断
SELECT 字段列表 FROM 表 WHERE 字段名 = (子查询);
多行单列:作为条件值,使用 in 等关键字进行条件判断
SELECT 字段列表 FROM 表 WHERE 字段名 in (子查询);
多行多列:作为虚拟表
SELECT 字段列表 FROM (子查询) WHERE 条件;
五、事务
简介四大特征
事务简介
数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令
事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败
事务是一个不可分割的工作逻辑单元
事务四大特征
原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
隔离性(Isolation):多个事务之间,操作的可见性
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
MySQL 事务默认自动提交
-- 查看事务的默认提交方式
SELECT @@autocommit;
-- 1 自动提交 0 手动提交
-- 修改事务提交方式
set @@autocommit = 0;
六、JDBC
1_简介
JDBC 概念:
JDBC 就是使用 Java 语言操作关系型数据库的一套 API
全称: (Java DataBase Connectivity) Java 数据库连接
JDBC 本质:
官方 (sun 公司) 定义的一套操作所有关系型数据库的规则,即接口
各个数据库厂商去实现这套接口,提供数据库驱动 jar 包
我们可以使用这套接口 (JDBC) 编程,真正执行的代码是驱动 jar 包中的实现类
JDBC 好处:
各数据库厂商使用相同的接口,Java 代码不需要针对不同数据库分别开发
可随时替换底层数据库,访问数据库的 Java 代码基本不变
(右侧图示辅助理解:通过 “MySQL 驱动” 连接 Java 代码与 MySQL 数据库 )
2_快速入门
0.创建工程,导入驱动 jar 包
mysql-connector-java-5.1.48.jar
1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
这里该类在 MySQL Connector/J 8.0 之后已被弃用,新版本推荐使用 com.mysql.cj.jdbc.Driver
2.获取连接
Connection conn = DriverManager.getConnection(url, username, password);
3.定义 SQL 语句
String sql = "update...";
4.获取执行 SQL 对象
Statement stmt = conn.createStatement();
5.执行 SQL
stmt.executeUpdate(sql);
6.处理返回结果
7释放资源
3_API详解DriverManager
DriverManager
DriverManager (驱动管理类) 作用:
注册驱动
获取数据库连接
1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
查看 Driver 类源码
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
提示:
MySQL 5 之后的驱动包,可以省略注册驱动的步骤
自动加载 jar 包中 META-INF/services/java.sql.Driver 文件中的驱动类
2.获取连接
static Connection getConnection(String url, String user, String password)
参数
1.url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
示例:jdbc:mysql://127.0.0.1:3306/db1
细节:
如果连接的是本机 mysql 服务器,并且 mysql 服务默认端口是 3306,则 url 可以简写为:jdbc:mysql:///数据库名称?参数键值对
配置 useSSL=false 参数,禁用安全连接方式,解决警告提示
2.user:用户名
3.password:密码
4_API详解Connection
Connection
Connection (数据库连接对象) 作用:
获取执行 SQL 的对象
管理事务
1.获取执行 SQL 的对象
普通执行 SQL 对象
Statement createStatement()
预编译 SQL 的执行 SQL 对象:防止 SQL 注入
PreparedStatement prepareStatement(sql)
执行存储过程的对象
CallableStatement prepareCall(sql)
2.事务管理
MySQL 事务管理
开启事务:BEGIN; / START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MySQL默认自动提交事务
JDBC 事务管理:Connection 接口中定义了 3 个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务
提交事务:commit()
回滚事务:rollback()
5_API详解Statement
Statement
Statement 作用:
执行 SQL 语句
int executeUpdate(sql):执行DML、DDL语句
返回值: (1) DML语句影响的行数 (2) DDL语句执行后,执行成功也可能返回 0
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet结果集对象
6_API详解ResultSet
ResultSet
ResultSet (结果集对象) 作用:
封装了 DQL 查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL 语句,返回 ResultSet 对象
获取查询结果
boolean next(): (1) 将光标从当前位置向前移动一行 (2) 判断当前行是否为有效行
返回值:
• true: 有效行,当前行有数据
• false: 无效行,当前行没有数据
xxx getXxx(参数):获取数据
xxx: 数据类型;如: int getInt(参数);String getString(参数)
参数:
• int: 列的编号,从1开始
• String: 列的名称
使用步骤:
1.游标向下移动一行,并判断该行否有数据: next ()
2.获取数据: getXxx (参数)
//循环判断游标是否是最后一行末尾
while(rs.next()){
//获取数据
rs.getXxx(参数);
}
package com.itheima.jdbc;import org.junit.Test;import java.sql.*;//JDBC快速入门 public class JDBCDemo7_PreparedStatement {@Testpublic void PreparedStatement() throws Exception {//2. 获取连接: 如果连接的是本机mysql并且端口是默认的 3306 可以简化书写String url = "jdbc:mysql:///test?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);// 接收用户输入 用户名和密码String name = "zhangsan";String pwd = "123";// 定义sqlString sql = "select * from tb_user where username = ? and password = ?";// 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);// 设置?的值pstmt.setString(1, name);pstmt.setString(2, pwd);// 执行sqlResultSet rs = pstmt.executeQuery();// 判断登录是否成功if(rs.next()){System.out.println("登录成功~");}else{System.out.println("登录失败~");}//7. 释放资源rs.close();pstmt.close();conn.close();} }
7_API详解PreparedStatement
PreparedStatement
PreparedStatement 作用:
预编译 SQL 语句并执行:预防 SQL 注入问题
SQL 注入
SQL 注入是通过操作输入来修改事先定义好的 SQL 语句,用以达到执行代码对服务器进行攻击的方法。
① 获取 PreparedStatement 对象
// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
② 设置参数值
PreparedStatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型;如 setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始
参数2:?的值
③ 执行 SQL
executeUpdate(); / executeQuery(); :不需要再传递sql
PreparedStatement 原理
PreparedStatement 好处:
1.预编译 SQL,性能更高
2.防止 SQL 注入:将敏感敏感字符进行转义
① PreparedStatement 预编译功能开启: useServerPrepStmts=true
② 配置 MySQL 执行日志 (重启 mysql 服务后生效)
log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2
PreparedStatement 原理:
1.在获取 PreparedStatement 对象时,将 sql 语句发送给 mysql 服务器进行检查,编译(这些步骤很耗时)
2.执行时就不用再进行这些步骤了,速度更快
3.如果 sql 模板一样,则只需要进行一次检查、编译