Knowledge note
正在加载知识笔记
正在加载知识笔记
Knowledge note
课前回顾:
1.条件查询:
select 列名 from 表名 where 条件
2.排序: order by
3.分组: group by
4.分页: limit m,n
5.聚合:聚合函数
count sum avg max min
6.having和where的区别:
where用在分组之前
having用在分组之后
7.模糊查询: like '' -> % 代表0个或者多个字符 _代表一个字符
8.多表关系:
a.一对一:正着看,倒着看都是一对一
b.一对多:正着看一对多,倒着看一对一
c.多对多:正反都是一对多
9.内连接:
select 列名 from 表A join 表B on 条件
select 列名 from 表A,表B where 条件
10.外连接:
a.左外连接: select 列名 from 表A left join 表B on 条件
b.右外连接: select 列名 from 表A right join 表B on 条件
11.内外连接的区别:
a.左外连接:查询的是和右表的交集以及左表未交集部分
b.右外连接:查询的是和左表的交集以及右表未交集部分
c.内连接:只查询交集部分
12.子查询:
一个select语句作为另外一条select语句的条件使用
今日重点:
1.会判断函数,字符串函数
2.从第三章,第四章都是重点
1.函数都是对指定的列进行操作
2.函数都是用在select后面
函数
用法
CONCAT(S1,S2,......,Sn)
连接S1,S2,......,Sn为一个字符串
CONCAT_WS(separator, S1,S2,......,Sn)
连接S1一直到Sn,并且中间以separator作为分隔符
UPPER(s) 或 UCASE(s)
将字符串s的所有字母转成大写字母
LOWER(s) 或LCASE(s)
将字符串s的所有字母转成小写字母
TRIM(s)
去掉字符串s开始与结尾的空格
SUBSTRING(s,index,len)
返回从字符串s的index位置其len个字符
-- 用户表
CREATE TABLE t_user (
id int(11) NOT NULL AUTO_INCREMENT,
uname varchar(40) DEFAULT NULL,
age int(11) DEFAULT NULL,
sex int(11) DEFAULT NULL,
PRIMARY KEY (id)
);
insert into t_user values (null,'zs',18,1);
insert into t_user values (null,'ls',20,0);
insert into t_user values (null,'ww',23,1);
insert into t_user values (null,'zl',24,1);
insert into t_user values (null,'lq',15,0);
insert into t_user values (null,'hh',12,0);
insert into t_user values (null,'wzx',60,null);
insert into t_user values (null,'lb',null,null);
字符串连接函数主要有2个:
函数或操作符
描述
concat(str1, str2, ...)
字符串连接函数,可以将多个字符串进行连接
concat_ws(separator, str1, str2, ...)
可以指定间隔符将多个字符串进行连接;
练习1:使用concat函数显示出 你好uname 的结果
/*
concat(str1, str2, ...)
字符串连接函数,可以将多个字符串进行连接
concat_ws(separator, str1, str2, ...)->可以指定间隔符将多个字符串进行连接
*/
-- 拼接字符串练习 练习1:使用concat函数显示出 你好uname 的结果
SELECT CONCAT('你好',uname) uname,age,sex FROM t_user;
练习2:使用concat_ws函数显示出 你好,uname 的结果
-- 练习2:使用concat_ws函数显示出 你好,uname 的结果SELECT CONCAT_WS(',','你好',uname) uname,age,sex FROM t_user;
字符串大小写处理函数主要有2个:
函数或操作符
描述
upper(str)
得到str的大写形式
lower(str)
得到str的小写形式
练习1: 将字符串 uname 转换为大写显示
-- 将hello转成大写
-- 查询t_user,uname变成大写
-- 将hello转成大写
SELECT UPPER('hello');
-- 查询t_user,uname变成大写
SELECT UPPER(uname) uname,age,sex FROM t_user;
练习2:将uname 转换为小写显示
-- 查询t_user,uname变成小写
SELECT LOWER(uname) uname,age,sex FROM t_user;
可以对字符串进行按长度填充满、也可以移除空格符
函数或操作符
描述
trim(str)
将str两边的空白符移除
练习1: 将用户id为9的用户的姓名的两边空白符移除
-- 将用户id为9的用户的姓名的两边空白符移除
-- 将用户id为9的用户的姓名的两边空白符移除
SELECT TRIM(uname) uname,age,sex FROM t_user;
字符串也可以按条件进行截取,主要有以下可以截取子串的函数;
函数或操作符
描述
substr()、substring()
获取子串: 1:substr(str, pos) 、substring(str, pos); 2:substr(str, pos, len)、substring(str, pos, len)
/*
substring(str, pos)
str:被截取的字符串
pos:从第几个字符开始截取
substring(str, pos, len)
str:被截取的字符串
pos:从第几个字符开始截取
len:截取多少个
*/
SELECT SUBSTRING('abcdefg',3);
SELECT SUBSTRING('abcdefg',3,2);
练习1:获取 hello,world 从第二个字符开始的完整子串
自己写
练习2:获取 hello,world 从第二个字符开始但是长度为4的子串
自己写
函数
用法
ABS(x)
返回x的绝对值
CEIL(x)
返回大于x的最小整数值
FLOOR(x)
返回小于x的最大整数值
RAND()
返回0~1的随机值
POW(x,y)
返回x的y次方
-- 练习1: 获取 -12 的绝对值
-- 练习2: 将 -11.2 向上取整
-- 练习3: 将 1.6 向下取整
-- 练习4: 获得2的2次幂的值
-- 练习5: 获得一个在0-100之间的随机数
-- 练习1: 获取 -12 的绝对值
SELECT ABS(-12);
-- 练习2: 将 -11.2 向上取整
SELECT CEIL(-11.2);
-- 练习3: 将 1.6 向下取整
SELECT FLOOR(1.6);
-- 练习4: 获得2的2次幂的值
SELECT POW(2,2);
-- 练习5: 获得一个在0-100之间的随机数
SELECT RAND()*100;
函数
用法
CURDATE() 或 CURRENT_DATE()
返回当前日期 年月日
CURTIME() 或 CURRENT_TIME()
返回当前时间 时分秒
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP()
返回当前系统日期时间
DATEDIFF(date1,date2) / TIMEDIFF(time1, time2)
返回date1 - date2的日期间隔 / 返回time1 - time2的时间间隔
-- 练习1:获取当前的日期(仅仅需要年月日)
-- 练习2: 获取当前的时间(仅仅需要时分秒)
-- 练习3: 获取当前日期时间(包含年月日时分秒)
-- 练习4: 获取到12月1日还有多少天
-- 练习1:获取当前的日期(仅仅需要年月日)
SELECT CURDATE();
-- 练习2: 获取当前的时间(仅仅需要时分秒)
SELECT CURTIME();
-- 练习3: 获取当前日期时间(包含年月日时分秒)
SELECT NOW();
-- 练习4: 获取到5月1日还有多少天
SELECT DATEDIFF('2025-5-1',NOW());
函数
用法
IF(比较,t ,f)里面的t和f是两个结果
如果比较是真,返回t,否则返回f
IFNULL(value1, value2)
如果value1不为空,返回value1,否则返回value2
CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2 .... [ELSE resultn] END
相当于Java的if...else if...else...
练习1:获取用户的姓名、性别,如果性别为1则显示'男',否则显示'女';要求使用if函数查询:
练习2:获取用户的姓名、性别,如果性别为null则显示为0;要求使用ifnull函数查询:
SELECT
uname,
CASE
WHEN age <= 12
THEN '儿童'
WHEN age <= 18
THEN '少年'
WHEN age <= 40
THEN '中年'
ELSE '老年' END age,
sex
FROM
t_user ;
我们现在默认使用的都是root用户,超级管理员,拥有全部的权限。但是,一个公司里面的数据库服务器上面可能同时运行着很多个项目的数据库。所以,我们应该根据不同的项目建立不同的用户,分配不同的权限来管理和维护数据库。
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
关键字说明:
1.用户名:创建的用户名
2.主机名:指定该用户在哪个主机上可以登录,如果是本地用户,可以用'localhost',如果想让该用户可以任意远程主机登录,可以使用通配符%
3.密码:该用户登录的密码,密码可以为空,如果为空,该用户可以不输入密码就可以登录mysql
具体操作:
-- user1用户只能在localhost这个IP登录mysql服务器
CREATE USER 'user1'@'localhost' IDENTIFIED BY '123';
-- user2用户可以在任何电脑上登录mysql服务器
CREATE USER 'user2'@'%' IDENTIFIED BY '123';
用户创建之后,基本没什么权限!需要给用户授权
授权格式:
GRANT 权限1, 权限2... ON 数据库名.表名 TO '用户名'@'主机名';
关键字说明:
a.GRANT:授权关键字
b.授予用户的权限,比如 'select' 'insert' 'update'等,如果要授予所有的权限,使用 'ALL'
c.数据库名.表名:该用户操作哪个数据库的哪些表,如果要授予该用户对所有数据库和表的相关操作权限,就可以用*表示: *.*
d.'用户名'@'主机名':给哪个用户分配权限
具体操作:
给user1用户分配对test这个数据库操作的权限
给user2用户分配对所有数据库操作的权限
REVOKE 权限1, 权限2... ON 数据库.表名 FROM '用户名'@'主机名';
具体操作:
撤销user1用户对test操作的权限
SHOW GRANTS FOR '用户名'@'主机名';
具体操作:
查看user1用户的权限
DROP USER '用户名'@'主机名';
具体操作:
删除user2
/*
分配用户:
create:创建
user:用户
'user1'@'localhost' : 用户名以及可以访问的主机地址
IDENTIFIED BY '123' : 分配密码
%:可以在任意远程主机上登录
*/
-- user1用户只能在localhost这个IP登录mysql服务器
CREATE USER 'user1'@'localhost' IDENTIFIED BY '123';
-- user2用户可以在任何电脑上登录mysql服务器
CREATE USER 'user2'@'%' IDENTIFIED BY '123';
/*
grant:分配权限关键字
grant后面跟的就是具体的操作权限:select insert update等,如果分配所有权限就写ALL
on:后面跟的是数据库名字 -> 指定啥数据库那么用此用户登录就只能看到哪个数据库名字
`220706_mysql03`.* -> 指定库中所有的表 * 代表所有,如果想要看到所有的库以及所有的表我们就写*.*
to:指明此权限要给的用户
*/
-- 给用户1分配权限
GRANT SELECT ON `230222_day02_2`.* TO 'user1'@'localhost';
-- 给用户2分配权限
GRANT ALL ON *.* TO 'user2'@'%';
/*
drop:删除用户关键字
*/
DROP USER 'user2'@'%';
DROP USER 'user1'@'localhost';
mysqladmin -uroot -p password 新密码 -- 新密码不需要加上引号
注意:需要在未登陆MySQL的情况下操作。
具体操作:
mysqladmin -uroot -p password root
输入老密码
set password for '用户名'@'主机名' = password('新密码');
注意:需要在登陆MySQL的情况下操作。
具体操作:
set password for 'user1'@'localhost' = password('666666');

1.概述:Java DataBase Connectivity(Java语言连接数据库)
2.为啥要用它:
将来我们不可能直接在数据库中写sql语句,我们肯定是将sql语句放到java代码中参与运行,所以我们就需要jdbc中的API
导包过程
1、找到mysql-connector-java-8.0.25.jar
2、新建lib文件夹复制jar包粘贴在这个文件夹下面
3、
1.导入JDBC核心jar包->只要是数据库操作,都要导这个核心包
mysql-connector-java-8.0.25.jar
2.JDBC技术中包含了一下四个对象:
a.DriverManager:驱动管理类
b.Connection接口:连接对象
c.Statement接口:执行sql语句
d.ResultSet接口:处理查询之后的结果集
数据库准备
用户名:Root
密码:123456
数据准备
CREATE DATABASE `250312_database03`;
-- 用户表
CREATE TABLE t_user (
id INT(11) NOT NULL AUTO_INCREMENT,
uname VARCHAR(40) DEFAULT NULL,
age INT(11) DEFAULT NULL,
sex INT(11) DEFAULT NULL,
PRIMARY KEY (id)
);
INSERT INTO t_user VALUES (NULL,'zs',18,1);
INSERT INTO t_user VALUES (NULL,'ls',20,0);
INSERT INTO t_user VALUES (NULL,'ww',23,1);
INSERT INTO t_user VALUES (NULL,'zl',24,1);
INSERT INTO t_user VALUES (NULL,'lq',15,0);
INSERT INTO t_user VALUES (NULL,'hh',12,0);
INSERT INTO t_user VALUES (NULL,'wzx',60,NULL);
INSERT INTO t_user VALUES (NULL,'lb',NULL,NULL);

1.注册驱动(可以省略) 为的是表明我们操作的是哪款数据库
DriverManager类
2.获取连接:Connection接口
a.获取:DriverManager类中的方法:
static Connection getConnection(String url, String user, String password)
b.参数:
url:写的是被操作库的地址
user:数据库用户名
password:数据库密码
3.准备sql:
写sql语句放到字符串
4.获取执行平台:Statement接口
a.获取:Connection中的方法
Statement createStatement()
5.执行sql:
a.方法:Statement接口中的方法
int executeUpdate(sql) -> 针对于增删改操作的
ResultSet executeQuery(sql) -> 针对于查询的,返回值类型是结果集对象
6.处理结果集:ResultSet接口
a.boolean next() 判断结果集中有没有下一个数据
b.获取数据
int getInt(int columnIndex)获取第几列的数据,传递的是第几列,主要获取int列的数据
int getInt(String columnLabel)获取指定列的数据,传递的是列名,主要获取int列的数据
String getString(int columnIndex)获取第几列的数据,传递的是第几列,主要获取varchar列的数据
String getString(String columnLabel)获取指定列的数据,传递的是列名,主要获取varchar列的数据
Object getObject(int columnIndex) 获取第几列的数据,传递的是第几列
Object getObject(String columnLabel)获取指定列的数据,传递的是列名
c.注意:
针对于增删改操作不需要处理结果集
针对于查询操作才需要处理结果集
7.关闭资源
close()方法 -> 连接对象,执行平台对象,结果集对象
CREATE TABLE `user`(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
`password` VARCHAR(20)
);
1.注意:其实我们不需要手动注册驱动,但是也要会
2.DriverManager类中的方法
static void registerDriver(Driver driver)
3.参数分析:Driver是一个接口,需要传递Driver接口的实现类
a.实现类:用的是mysql核心jar包中的 mysql.cj.jdbc.Driver
b.注意:我们打开jar中的Driver类发现了里面有一个静态代码块,其中已经注册了驱动了
所以我们再使用registerDriver注册驱动相当于注册了两次驱动,恶心
c.解决:我们直接想办法将jar中的Driver类加载到内存
Class.forName("mysql.cj.jdbc.Driver");
Class.forName("com.mysql.cj.jdbc.Driver");
其实我们不用自己手动注册驱动:jdbc会自动扫描一个包下的资源,自动注册
1.获取:DriverManager类中的方法
static Connection getConnection(String url, String user, String password)
2.参数分析:
a.url:被操作库的地址 -> jdbc:mysql://localhost:3306/数据库名字
jdbc:mysql://localhost:3306/数据库名字 这是一个请求地址,如果想让这个地址上带其他请求参数,就在后面加?,在?后面写请求参数,而请求参数都是key=value形式,多个键值对之间用&连接
比如: jdbc:mysql://localhost:3306/数据库名字?key=value&key=value
b.user:数据库用户名
c.password:数据库密码
//2.获取连接
String url = "jdbc:mysql://localhost:3306/250312_database03";
String name = "root";
String pwd = "123456";
Connection connection = DriverManager.getConnection(url, name, pwd);
System.out.println("connection = " + connection);
插入
package com.hjs;
import org.junit.Test;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.Statement;
public class Demo01JDBC {
@Test
public void insert() throws Exception {
//1注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2获取连接
String url = "jdbc:mysql://localhost:3306/250312_database03";
String name="root";
String pwd="123456";
Connection connection = DriverManager.getConnection(url, name, pwd);
/*3准备sql语句*/
String sql = "insert into t_user (uname,age) values('tom','111')";
/*4获取执行平台->获取执行sql的对象*/
Statement statement=connection.createStatement();
//5执行sql
statement.executeUpdate(sql);
//6释放资源
statement.close();
connection.close();
}
}
更新
@Test
public void update() throws Exception{
//获取连接
String url = "jdbc:mysql://localhost:3306/250312_database03";
String name="root";
String pwd="123456";
Connection connection = DriverManager.getConnection(url, name, pwd);
/*准备sql语句*/
String sql = "update t_user set age=18 where id=5";
/*获取执行平台->获取执行sql的对象*/
Statement statement=connection.createStatement();
//执行sql
statement.executeUpdate(sql);
//释放资源
statement.close();
connection.close();
}
删除
@Test
public void delete()throws Exception{
//2.获取连接
String url = "jdbc:mysql://localhost:3306/250312_database03";
String name = "root";
String pwd = "123456";
Connection connection = DriverManager.getConnection(url, name, pwd);
/*
3.准备sql语句
*/
String sql = "delete from t_user where id = 6";
/*
4.获取执行平台->获取执行sql的对象
*/
Statement statement = connection.createStatement();
//5.执行sql
statement.executeUpdate(sql);
//6.释放资源
statement.close();
connection.close();
}
1.可以将java代码中的sql语句放到sqlyog中检测一下是否正确
2.或者先从sqlyog中写完,粘贴到java代码中
1.执行查询的方法:Statement接口中的方法
ResultSet executeQuery(sql) -> 针对于查询的,返回值类型是结果集对象
2.处理结果集:ResultSet接口
a.boolean next() 判断结果集中有没有下一个数据
b.获取数据
int getInt(int columnIndex)获取第几列的数据,传递的是第几列,主要获取int列的数据
int getInt(String columnLabel)获取指定列的数据,传递的是列名,主要获取int列的数据
String getString(int columnIndex)获取第几列的数据,传递的是第几列,主要获取varchar列的数据
String getString(String columnLabel)获取指定列的数据,传递的是列名,主要获取varchar列的数据
Object getObject(int columnIndex) 获取第几列的数据,传递的是第几列
Object getObject(String columnLabel)获取指定列的数据,传递的是列名
@Test
public void select()throws Exception{
//2.获取连接
String url = "jdbc:mysql://localhost:3306/250312_database03";
String name = "root";
String pwd = "123456";
Connection connection = DriverManager.getConnection(url, name, pwd);
/*
3.准备sql语句
*/
String sql = "select * from t_user";
/*
4.获取执行平台->获取执行sql的对象
*/
Statement statement = connection.createStatement();
//5.执行sql
ResultSet rs = statement.executeQuery(sql);
//6.处理结果集
while(rs.next()){
int id = rs.getInt("id");
String username = rs.getString("uname");
String age = rs.getString("age");
System.out.println(id+"..."+username+"..."+age);
}
//7.释放资源
rs.close();
statement.close();
connection.close();
}

jdbc.properties
url=jdbc:mysql://localhost:3306/250312_database03
username=root
password=123456
JDBCUtils.java
package com.hjs.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JDBC 工具类
* 功能:
* 1. 从 jdbc.properties 中读取数据库连接信息
* 2. 提供获取连接的方法
* 3. 提供统一的资源关闭方法
*/
public class JDBCUtils {
// 私有构造方法:防止外部创建对象
private JDBCUtils() {}
// 定义三个静态变量保存数据库连接信息
private static String url = null; // 数据库URL
private static String username = null; // 用户名
private static String password = null; // 密码
// 静态代码块:类加载时自动执行一次,用于加载配置文件
static {
try {
// 1. 创建Properties对象
Properties properties = new Properties();
// 2. 通过类加载器读取resources目录下的配置文件
InputStream in = JDBCUtils.class.getClassLoader()
.getResourceAsStream("jdbc.properties");
// 3. 将文件内容加载到Properties中
properties.load(in);
// 4. 取出配置项
url = properties.getProperty("url");
username = properties.getProperty("uname");
password = properties.getProperty("pwd"); // 建议属性名改成pwd
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return Connection 连接对象
*/
public static Connection getConnection() {
Connection connection = null;
try {
// 通过DriverManager根据配置创建连接
connection = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 关闭数据库资源(按ResultSet → Statement → Connection顺序)
* @param connection 数据库连接
* @param statement SQL语句执行对象
* @param resultSet 查询结果集
*/
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
// 关闭结果集
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 关闭语句对象
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 关闭连接
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Demo02JDBC.java
package com.hjs;
import com.hjs.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Demo02JDBC {
@Test
public void insert() throws Exception {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = JDBCUtils.getConnection();
/*准备sql语句*/
String sql = "insert into t_user (uname,age) values('tom','111')";
/*获取执行平台->获取执行sql的对象*/
Statement statement=connection.createStatement();
//执行sql
statement.executeUpdate(sql);
//释放资源
JDBCUtils.close(connection,statement,null);
}
@Test
public void update() throws Exception{
//获取连接
Connection connection = JDBCUtils.getConnection();
/*准备sql语句*/
String sql = "update t_user set age=18 where id=5";
/*获取执行平台->获取执行sql的对象*/
Statement statement=connection.createStatement();
//执行sql
statement.executeUpdate(sql);
//释放资源
JDBCUtils.close(connection,statement,null);
}
@Test
public void delete()throws Exception{
//2.获取连接
Connection connection = JDBCUtils.getConnection();
/*
3.准备sql语句
*/
String sql = "delete from t_user where id = 6";
/*
4.获取执行平台->获取执行sql的对象
*/
Statement statement = connection.createStatement();
//5.执行sql
statement.executeUpdate(sql);
//6.释放资源
JDBCUtils.close(connection,statement,null);
}
@Test
public void select()throws Exception{
//2.获取连接
Connection connection = JDBCUtils.getConnection();
/*
3.准备sql语句
*/
String sql = "select * from t_user";
/*
4.获取执行平台->获取执行sql的对象
*/
Statement statement = connection.createStatement();
//5.执行sql
ResultSet rs = statement.executeQuery(sql);
//6.处理结果集
while(rs.next()){
int id = rs.getInt("id");
String username = rs.getString("uname");
String age = rs.getString("age");
System.out.println(id+"..."+username+"..."+age);
}
//7.释放资源
JDBCUtils.close(connection,statement,rs);
}
}
1.函数:
select last_insert_id();
2.前提:主键id在添加的时候我们自己不要维护,让mysql自动维护
public class Demo03JDBC {
@Test
public void lastInsertId()throws Exception{
//获取连接
Connection connection = JDBCUtils.getConnection();
//准备sql
String insertSql = "insert into user (username,password) values ('zhaoliu','666')";
String lastInsertId = "select last_insert_id()";
//获取执行sql的对象
Statement statement = connection.createStatement();
//执行sql
statement.executeUpdate(insertSql);
ResultSet resultSet = statement.executeQuery(lastInsertId);
while(resultSet.next()){
int id = resultSet.getInt(1);
System.out.println(id);
}
//关闭资源
JDBCUtils.close(connection,statement,resultSet);
}
}
INSERT INTO `user` (username,`password`) VALUES ('lisi','456');
#INSERT INTO `user` (uid,username,`password`) VALUES (9,'wangwu','456');
SELECT LAST_INSERT_ID();
public class Demo01Login {
public static void main(String[] args)throws Exception{
//1.创建Scanner对象
Scanner sc = new Scanner(System.in);
//2.提示用户输入用户名和密码
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
//3.获取连接
Connection connection = JDBCUtils.getConnection();
//4.准备sql
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
System.out.println(sql);
//5.获取执行sql的对象
Statement statement = connection.createStatement();
//6.执行sql
ResultSet rs = statement.executeQuery(sql);
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//7.关闭资源
JDBCUtils.close(connection,statement,rs);
}
}

密码输入:111' or '1' = '1 以上程序不行了->sql注入
1.概述:PreparedStatement是一个接口 -> 是 Statement接口的一个子接口
2.作用:防sql注入
3.特点:允许sql语句中用?,不是直接拼接字符串了,而是将值都用?占位,再单独为?赋值
4.获取:Connection中的方法
PreparedStatement prepareStatement(String sql)
5.此时写sql可以这么写:
String sql = "select * from user where username = ? and password = ?"
6.为?赋值:PreparedStatement中的方法
void setObject(int parameterIndex, Object x) -> 为指定的?赋值
parameterIndex:传递的是第几个? -> 1代表给第一个?赋值,2代表为第二个?赋值...
x:给?赋的具体的值
7.执行sql:
int executeUpdate() 针对于增删改操作
ResultSet executeQuery() 针对于查询操作

public class Demo02PreparedStatement {
@Test
public void insert()throws Exception{
// 1.获取连接
Connection connection = JDBCUtils.getConnection();
// 2.准备sql
String sql = "insert into user (username,password) values (?,?)";
//3.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
//4.给?设置参数
pst.setObject(1,"tianqi");
pst.setObject(2,"777");
//5.执行sql
pst.executeUpdate();
//6.释放资源
JDBCUtils.close(connection,pst,null);
}
@Test
public void delete()throws Exception{
// 1.获取连接
Connection connection = JDBCUtils.getConnection();
// 2.准备sql
String sql = "delete from user where uid = ?";
//3.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
//4.给?设置参数
pst.setObject(1,14);
//5.执行sql
pst.executeUpdate();
//6.释放资源
JDBCUtils.close(connection,pst,null);
}
@Test
public void update()throws Exception{
// 1.获取连接
Connection connection = JDBCUtils.getConnection();
// 2.准备sql
String sql = "update user set password = ? where uid = ?";
//3.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
//4.给?设置参数
pst.setObject(1,"777");
pst.setObject(2,13);
//5.执行sql
pst.executeUpdate();
//6.释放资源
JDBCUtils.close(connection,pst,null);
}
@Test
public void select()throws Exception{
// 1.获取连接
Connection connection = JDBCUtils.getConnection();
// 2.准备sql
String sql = "select * from user";
//3.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
//5.执行sql
ResultSet rs = pst.executeQuery();
while(rs.next()){
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(username+"..."+password);
}
//6.释放资源
JDBCUtils.close(connection,pst,rs);
}
}
?只能代表值
public class Demo01Login {
public static void main(String[] args)throws Exception{
//1.创建Scanner对象
Scanner sc = new Scanner(System.in);
//2.提示用户输入用户名和密码
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
//3.获取连接
Connection connection = JDBCUtils.getConnection();
//4.准备sql
String sql = "select * from user where username = ? and password = ?";
System.out.println(sql);
//5.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
pst.setObject(1,username);
pst.setObject(2,password);
//6.执行sql
ResultSet rs = pst.executeQuery();
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//7.关闭资源
JDBCUtils.close(connection,pst,rs);
}
}
select * from user where username = 'tom' and password = '111' or '1' = '1'
如果用的是PreparedStatement即使传入了111' or '1' = '1,拼接到了sql语句中会自动将输入'转义
变成了:
select * from user where username = 'tom' and password = '111\' or \'1\' = \'1'
123\' or \'1\' = \'1 是一整个大的字符串,被包裹在了''中
?只能给sql语句中的具体的数据占位
完成注册功能:作业
输入用户名和密码
根据用户名查询,是否有该用户
如果有,注册失败
否则,将用户名和密码insert到数据库中,显示注册成功
CREATE TABLE category(
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(10)
);
1.注意:
a.mysql默认情况下不会批量添加,添加的时候都是一条一条添加的,我们这里所说的批量添加其实就是将多个要添加的数据先打包到内存,然后再将打包好的数据一起添加到数据库中,这样的话我们的效率会提高
b.由于mysql默认情况下不会批量添加,所以我们想要进行批量添加的操作,需要手动开启此功能
2.怎么开启:需要在数据库url后面加入开启批量添加的参数-> rewriteBatchedStatements=true
jdbc:mysql://localhost:3306/241023_database3?rewriteBatchedStatements=true
3.方法:用到PreparedStatement中的方法:
void addBatch() -> 将一组数据保存起来,给数据打包,放到内存中
executeBatch() -> 将打包好的数据一起发送给mysql
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/250312_database03?rewriteBatchedStatements=true
username=root
password=root
public class JDBCUtils {
private JDBCUtils() {
}
private static String url = null;
private static String name = null;
private static String pwd = null;
static {
try {
Properties properties = new Properties();
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(in);
Class.forName(properties.getProperty("driverClass"));
url = properties.getProperty("url");
name = properties.getProperty("username");
pwd = properties.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(url, name, pwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class Demo01AddBatch {
@Test
public void insert()throws Exception{
//1.获取连接
Connection connection = JDBCUtils.getConnection();
//2.准备sql
String sql = "insert into category(cname) values (?)";
//3.获取执行sql的对象
PreparedStatement pst = connection.prepareStatement(sql);
for(int i = 0;i<1000;i++){
pst.setObject(1,"水果"+i);
//4.将数据一起打包到内存中
pst.addBatch();
}
//5.执行sql
pst.executeBatch();
//6.释放资源
JDBCUtils.close(connection,pst,null);
}
}
知识笔记会随着实践和认知变化持续更新,不代表最终结论。