day03.函数_jdbc
课前回顾:
1.聚合函数:对列进行操作,会产生单个数据
count(列名):统计总记录数
sum(列名):对指定列求和
avg(列名):对指定列求平均值
max(列名):求指定列的最大值
min(列名):求指定列的最小值
2.分组查询:group by
having:在分组之后进行筛选
按照哪一列分组呢:相同的在一组,不同的在一组
3.分页: limit m,n
m:代表的是每页的起始位置
n:代表的是每页显示条数
起始位置:(当前页-1)*每页显示条数
总记录数:count统计
总页数:Math.ceil(总记录数/每页显示条数)
4.mysql三范式:
原子性,唯一性,不可依赖性
5.多表关系:一对多 多对多 一对一
6.交叉查询:select 列名 from 表A,表B->笛卡尔乘积
7.内连接:inner join on
8.外连接:
a.左外连接:left outer join
b.右外连接:right outer join
c.怎么区分左表和右表:看join,在join左边的就是左表,join右边的就是右表
d.左外连接,右外连接,内连接区别:
左:查询的是和右表的交集,以及左表的全部
右:查询的是和左表的交集,以及右表的全部
内:只查交集
9.子查询:一个查询语句作为另外一个查询语句的条件使用
查询出来的结果还可以作为伪表使用
10.UNION:将两个查询结果合并,去重复
11.函数:字符串中的函数,用法其实和聚合函数一样,都是针对某一列的数据进行操作
今日重点:
从第三章开始,都是重点
第一章.MySQL的常用函数
-- 用户表
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.1 数值函数
1.1.1 数值函数列表
函数 | 用法 |
---|---|
ABS(x) | 返回x的绝对值 |
CEIL(x) | 返回大于x的最小整数值 |
FLOOR(x) | 返回小于x的最大整数值 |
RAND() | 返回0~1的随机值 |
POW(x,y) | 返回x的y次方 |
1.1.2 常用数值函数练习
练习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;
1.2 日期函数
1.2.1 日期函数列表
函数 | 用法 |
---|---|
CURDATE() 或 CURRENT_DATE() | 返回当前日期 年月日 |
CURTIME() 或 CURRENT_TIME() | 返回当前时间 时分秒 |
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP() | 返回当前系统日期时间 |
DATEDIFF(date1,date2) / TIMEDIFF(time1, time2) | 返回date1 - date2的日期间隔 / 返回time1 - time2的时间间隔 |
1.2.2 常用日期函数的练习
练习1:获取当前的日期
SELECT CURDATE();
练习2: 获取当前的时间(仅仅需要时分秒)
SELECT CURTIME();
练习3: 获取当前日期时间(包含年月日时分秒)
SELECT NOW();
练习4: 获取到五一还有多少天
SELECT DATEDIFF('2022-05-01',CURDATE());
1.3 流程函数_判断
函数 | 用法 |
---|---|
IF(比较,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则显示1,否则显示0;要求使用if函数查询:
SELECT uname,IF(sex=1,1,0) 'sex' FROM t_user;
-
练习2:获取用户的姓名、性别,如果性别为null则显示为0;要求使用ifnull函数查询:
SELECT uname,IFNULL(sex,0) FROM t_user;
-
练习3:如果age<=12,显示儿童,如果age<=18,显示少年,如果age<=40,显示中年,否则显示老年
SELECT id,uname,CASE WHEN age<=12 THEN '儿童' WHEN age<=18 THEN '少年' WHEN age<=40 THEN '中年' ELSE '老年' END '年龄段',IFNULL(sex,0) 'sex' FROM t_user;
CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2 .... [ELSE resultn] END case when:相当于if when:相当于else if THEN:后面跟条件对应的结果 判断完毕,用end结束
第二章 DCL语句
我们现在默认使用的都是root用户,超级管理员,拥有全部的权限。但是,一个公司里面的数据库服务器上面可能同时运行着很多个项目的数据库。所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限来管理和维护数据库。
2.1 创建用户
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';
2.2 授权用户
用户创建之后,基本没什么权限!需要给用户授权
授权格式:
GRANT 权限1, 权限2... ON 数据库名.表名 TO '用户名'@'主机名';
关键字说明:
a.GRANT:授权关键字
b.授予用户的权限,比如 'select' 'insert' 'update'等,如果要授予所有的权限,使用 'ALL'
c.数据库名.表名:该用户操作哪个数据库的哪些表,如果要授予该用户对所有数据库和表的相关操作权限,就可以用*表示: *.*
d.'用户名'@'主机名':给哪个用户分配权限
具体操作:
-
给user1用户分配对test这个数据库操作的权限
GRANT CREATE,ALTER,DROP,INSERT,UPDATE,DELETE,SELECT ON test.* TO 'user1'@'localhost';
-
给user2用户分配对所有数据库操作的权限
GRANT ALL ON *.* TO 'user2'@'%';
2.3 撤销授权
REVOKE 权限1, 权限2... ON 数据库.表名 FROM '用户名'@'主机名';
具体操作:
-
撤销user1用户对test操作的权限
REVOKE ALL ON test.* FROM 'user1'@'localhost';
2.4 查看权限
SHOW GRANTS FOR '用户名'@'主机名';
具体操作:
-
查看user1用户的权限
SHOW GRANTS FOR 'user1'@'localhost';
2.5 删除用户
DROP USER '用户名'@'主机名';
具体操作:
-
删除user2
DROP USER 'user2'@'%';
/*
1.创建用户:
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
2.关键字介绍:
a.用户名:创建的用户名
b.主机名:指定该用户在哪个主机上登录,如果是本地用户,可以用'localhost',
如果想让该用户可以任意远程主机登录,可以使用通配符%
c.密码:该用户登录的密码,密码可以为空,如果为空,该用户可以不输入密码就可以登录mysql
*/
-- user1用户只能在localhost这个IP上登录mysql服务器,密码为123
CREATE USER 'user1'@'localhost' IDENTIFIED BY '123';
-- user2用户可以在任何电脑上登录mysql服务器,密码为123
CREATE USER 'user2'@'%' IDENTIFIED BY '123';
/*
2.分配用户的权限:
GRANT 权限1, 权限2... ON 数据库名.表名 TO '用户名'@'主机名';
关键字介绍:
a.GRANT:授权关键字
b.权限1,权限2...:授予用户的权限
比如:select,insert,update,代表该用户只能对数据进行查询,添加,修改操作
如果要授予所有的权限,使用 ALL
c.数据库名.表名:该用户可以操作哪个库的哪些表
如果要授予该用户对所有数据库和表的相关操作权限,可以用*表示: *.*
如果要是授予该用户指定库中的所有表相关操作权限,可以用: 库名.*
d.'用户名'@'主机名':给哪个用户分配权限
e.注意:授权时,用户名和主机名要和创建用户的时候指定的要对应
*/
GRANT CREATE,ALTER,DROP,INSERT,UPDATE,SELECT ON 220227_java2_2.* TO 'user1'@'localhost';
GRANT ALL ON *.* TO 'user2'@'%';
/*
3.删除用户:
DROP USER '用户名'@'主机名';
注意:删除用户的时候,用户名和主机名要和创建用户的时候指定的要对应
*/
DROP USER 'user2'@'%';-- 正确
DROP USER 'user2'@'localhost';-- 错误,在创建user2的时候,主机名是%不是localhost
2.6 修改用户密码
2.6.1 修改管理员密码
mysqladmin -uroot -p password 新密码 -- 新密码不需要加上引号
注意:需要在未登陆MySQL的情况下操作。
具体操作:
mysqladmin -uroot -p password root
输入老密码
2.6.2 修改普通用户密码
set password for '用户名'@'主机名' = password('新密码');
注意:需要在登陆MySQL的情况下操作。
具体操作:
set password for 'user1'@'localhost' = password('666666');
第三章.JDBC
1.JDBC介绍
1.问题描述:将来开发,我们不能直接在mysql环境中写sql语句,我们需要将sql语句放到java代码逻辑中
所以我们就需要将java代码中的sql语句执行起来,从而间接操作mysql数据库中的数据
2.那么怎么让java代码中的sql语句执行呢?->需要用到java中的api了-> JDBC技术
3.JDBC概述:用于操作数据库的java技术,此技术包含了很多操作数据库的接口,对象,方法,是一种标准
Java DataBase Connectivity->java数据库连接技术
4.JDBC中四大核心接口:
a.DriverManager 类 用户注册驱动
b.Connection 接口 用于连接数据库,获取连接
c.Statement 接口 用于执行sql语句
d.ResultSet 接口 用于处理结果集->针对于查询
思路小技巧:首先要指明操作哪款数据库(注册驱动,DriverManager),然后连上数据库(获取连接,Connection接口),再然后执行sql语句操作数据库(执行sql,Statement接口) ,最后查询结果有很多数据,需要放到集合中,然后遍历集合获取查询出来的数据(处理结果集,ResultSet接口)
2.JDBC准备(导入jar包)
1.导入操作数据库的核心jar包:只要是用java代码操作数据库,都离不开这个jar包
mysql-connector-java-8.0.25.jar
2.如何导包:
a.在当前模块下,创建文件夹,取名为lib
b.将要使用的jar包粘贴到lib下
c.解压jar包到当前模块环境下->对着lib右键->add as library
d.level选择module
e.点击ok,jar包导入成功
3.JDBC开发步骤以及详解
1.注册驱动 DriverManager类
2.获取连接 Connection接口
DriverManager类中的方法:
static Connection getConnection(数据库地址, 数据库登录用户名, 数据库登录密码)
3.获取执行平台 Statement接口->用于执行sql语句
Connection接口中的方法:
Statement createStatement()
4.执行sql Statement中的方法
Statement中的方法:针对不用的sql语句,调用不同的方法去执行
int executeUpdate(String sql) -> 针对于增删改操作
ResultSet executeQuery(String sql)->针对于查询操作,要处理结果集
5.处理结果集 ResultSet接口
a.针对于增删改操作,不用处理结果集
b.针对于查询操作,用处理结果集:其实就是遍历结果集,将结果集中的查询结果获取出来
6.关闭资源 close()方法
4.JDBC注册驱动
1.注册驱动
a.用到的类:DriverManager
b.方法:static void registerDriver(Driver driver)->注册驱动
c.参数:Driver接口,调用registerDriver方法时需要传递Driver接口的实现类
Driver接口是:java.sql包下的接口
java.sql.Driver接口实现类在导入的jar包中:com.mysql.cj.jdbc.Driver
d.问题:如果使用DriverManager.registerDriver(new Driver());注册驱动,其实不合适
原因:通过翻阅Driver实现类的底层我们发现,里面有一个静态代码块,
在静态代码块中也写了DriverManager.registerDriver(new Driver());
如果我们用DriverManager.registerDriver(new Driver());注册驱动,那么驱动
将会注册两次,没必要
e.如何写才能保证Driver驱动只注册一次呢?
我们不写DriverManager.registerDriver了,我们直接将Driver实现类加载到内存
Driver实现类中的静态代码块自然就给我们注册驱动了
直接反射Driver类,直接就将com.mysql.cj.jdbc.Driver加载到内存了,自然也就执行
静态代码块了
Class.forName("com.mysql.cj.jdbc.Driver");
5.JDBC获取连接
1.获取连接:Connection接口
a.获取:DriverManager类中的方法:
static Connection getConnection(String url, String user, String password)
b.参数说明:
url:数据库地址 jdbc:mysql://localhost:3306/数据库名字?时区&其他参数
user:数据库登录用户名 root
password:数据库登录密码
2.注意细节:
a.mysql8中导入的jar包如果是mysql-connector-java-8.0.19.jar需要指定时区
serverTimezone=UTC
UTC是世界协调时间
mysql8中导入的jar包如果是mysql-connector-java-8.0.25.jar不需要指定时区
b.rewriteBatchedStatements=true 代表可以批量添加执行添加sql语句
mysql默认,不能批量执行添加语句,他会将多条sql拆散,一句一句执行
如果添加了此参数rewriteBatchedStatements=true,mysql就会批量执行添加语句
c.url中?后面写的就是参数
参数都是key=value形式,每一组参数用&连接
请求路径?参数&参数
//2.获取连接
String url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
String name = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, name, password);
System.out.println(connection);
细节:
1.使用:mysql-connector-java-8.0.19.jar,url上需要加时区 使用:mysql-connector-java-8.0.25.jar,url上不需要加时区 如果记不清,那么直接都加上,咱们就不考虑小版本区别,直接粘贴以下代码: jdbc:mysql://localhost:3306/数据库名字?serverTimezone=UTC&rewriteBatchedStatements=true
2.常见错误
3.连接数据库用的啥协议: TCP协议
6.JDBC实现增删改操作
-- 准备工作
CREATE TABLE `user`(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(10),
`password` VARCHAR(10)
);
/*
添加功能
*/
@Test
public void add()throws Exception{
/*
1.注册驱动
a.用到的类:DriverManager
b.方法:static void registerDriver(Driver driver)->注册驱动
c.参数:Driver接口,调用registerDriver方法时需要传递Driver接口的实现类
Driver接口是:java.sql包下的接口
java.sql.Driver接口实现类在导入的jar包中:com.mysql.cj.jdbc.Driver
d.问题:如果使用DriverManager.registerDriver(new Driver());注册驱动,其实不合适
原因:通过翻阅Driver实现类的底层我们发现,里面有一个静态代码块,
在静态代码块中也写了DriverManager.registerDriver(new Driver());
如果我们用DriverManager.registerDriver(new Driver());注册驱动,那么驱动
将会注册两次,没必要
e.如何写才能保证Driver驱动只注册一次呢?
我们不写DriverManager.registerDriver了,我们直接将Driver实现类加载到内存
Driver实现类中的静态代码块自然就给我们注册驱动了
直接反射Driver类,直接就将com.mysql.cj.jdbc.Driver加载到内存了,自然也就执行
静态代码块了
*/
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
String name = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, name, password);
/*
3.获取执行平台-> Statement接口-> 执行sql
Connection接口下的方法:Statement createStatement()
*/
Statement st = connection.createStatement();
/*
4.执行sql:Statement接口中的方法
int executeUpdate(String sql)-> 针对于增删改操作->不用处理结果集
ResultSet executeQuery(String sql) -> 针对于查询操作,由于查询出来时有很多数据,所以需要容器存放,所以返回结果集
*/
String sql = "insert into user(username,password) values ('柳岩','5436')";
int result01 = st.executeUpdate(sql);
System.out.println("result01 = " + result01);
/*
5.处理结果集
针对于增删改来说不用处理结果集
*/
/*
6.关闭资源
统一用close()
*/
st.close();
connection.close();
}
/**
* 删除功能
*/
@Test
public void delete()throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
String name = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, name, password);
//3.获取执行平台
Statement st = connection.createStatement();
//4.执行sql
String sql = "delete from user where uid = 2";
int result01 = st.executeUpdate(sql);
System.out.println("result01 = " + result01);
//5.处理结果集-> 增删改操作不用处理结果集,直接不写了
//6.关闭资源
st.close();
connection.close();
}
/**
* 修改功能
*/
@Test
public void update()throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
String name = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, name, password);
//3.获取执行平台
Statement st = connection.createStatement();
//4.执行sql
String sql = "update user set password = '6666' where uid = 4";
int result01 = st.executeUpdate(sql);
System.out.println("result01 = " + result01);
//5.处理结果集-> 增删改操作不用处理结果集,直接不写了
//6.关闭资源
st.close();
connection.close();
}
细节:
1.sql代码在java语句中:可以带上``,可以不带
2.sql代码在java语句中,最后可以加;也可以不加
3.如果不确定sql是否写的正确,可以将java中的sql语句放到sqlyog中验证一下
或者先在sqlyog中写完sql,然后粘到java中
7.JDBC实现查询操作
1.执行查询语句的方法:
ResultSet executeQuery(String sql) -> 针对于查询操作,由于查询出来时有很多数据,所以需要容器存放,所以返回结果集
2.处理结果集:从ResultSet中获取查询的数据->查询出来的数据会先封到ResultSet中,我们需要从ResultSet中获取查询的数据
boolean next()->判断结果集中是否有下一个元素
3.获取结果集中的数据
int getInt(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
int getInt(String columnLabel) -> 获取指定列的数据
columnLabel:写的是列名
String getString(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
String getString(String columnLabel) -> 获取指定列的数据
columnLabel:写的是列名
Object getObject(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
Object getObject(String columnLabel)-> 获取指定列的数据
columnLabel:写的是列名
/**
* 查询功能
*/
@Test
public void query()throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
String name = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, name, password);
//3.获取执行平台
Statement st = connection.createStatement();
//4.执行sql
String sql = "select * from user";
ResultSet rs = st.executeQuery(sql);
//5.处理结果集
while(rs.next()){
//int uid = rs.getInt(1);
//int uid = rs.getInt("uid");
//System.out.println(uid);
//String uid = rs.getString(1);
//System.out.println(uid);
//String username = rs.getString("username");
//System.out.println(username);
Object uid = rs.getObject("uid");
Object username = rs.getObject("username");
Object pwd = rs.getObject("password");
System.out.println(uid+"..."+username+"..."+pwd);
}
//6.关闭资源
rs.close();
st.close();
connection.close();
}
8.JDBC工具类使用
public class JDBCUtils {
private static String url;
private static String name;
private static String password;
/*
由于注册驱动和初始化url username password参数
应该最先执行,而且只执行一次即可
所以我们应该把这些代码放到静态代码块中
*/
static {
//注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
url = "jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true";
name = "root";
password = "root";
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConn() {
Connection connection = null;
try {
connection = DriverManager.getConnection(url, name, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 关闭资源
*/
public static void close(Connection connection, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class Test03_JDBC {
/**
* 查询功能
*/
@Test
public void query()throws Exception{
//2.获取连接
Connection conn = JDBCUtils.getConn();
//3.获取执行平台
Statement st = conn.createStatement();
//4.执行sql
String sql = "select * from user";
ResultSet rs = st.executeQuery(sql);
//5.处理结果集
while(rs.next()){
//int uid = rs.getInt(1);
//int uid = rs.getInt("uid");
//System.out.println(uid);
//String uid = rs.getString(1);
//System.out.println(uid);
//String username = rs.getString("username");
//System.out.println(username);
Object uid = rs.getObject("uid");
Object username = rs.getObject("username");
Object pwd = rs.getObject("password");
System.out.println(uid+"..."+username+"..."+pwd);
}
//6.关闭资源
JDBCUtils.close(conn,st,rs);
}
/**
* 添加功能
*/
@Test
public void add() throws Exception {
// 获取连接-> 一旦调用静态成员,类就会被加载到内存,静态代码块就要执行了
Connection conn = JDBCUtils.getConn();
//获取执行平台
Statement st = conn.createStatement();
//准备sql
String sql = "insert into user(username,password) values ('有菜','8888')";
//执行sql
st.executeUpdate(sql);
//关闭资源
JDBCUtils.close(conn,st,null);
}
}
第四章.PreparedStatement预处理对象
1.sql注入的问题以及解决方式(预处理对象)
public class Test01 {
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 conn = JDBCUtils.getConn();
//4.获取执行平台
Statement st = conn.createStatement();
//5.准备sql
/*
"select * from user where username = '" +username+ "' and password = '" +password+ "'"
*/
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
System.out.println(sql);
//6.执行sql
ResultSet rs = st.executeQuery(sql);
//7.处理结果集
if (rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//8.关闭资源
JDBCUtils.close(conn,st,rs);
}
}
密码输入:345’ or ‘1’ = '1 以上程序不行了->sql注入
2.使用预处理对象(PreparedStatement)实现操作
1.概述:PreparedStatement 是一个接口 是Statement接口的子接口
2.获取:使用Connection接口中的方法:
PreparedStatement prepareStatement(String sql) -> 获取PreparedStatement对象,传递sql语句
3.特点:
在执行sql的时候,sql语句支持使用占位符-> ?
String sql = "select * from username = ? and password = ?";
后面再对每一个?赋值
4.为占位符赋值:
void setObject(int parameterIndex, Object x)
parameterIndex:写的是第几个?
x:代表为?赋的值
5.执行sql:PreparedStatement中的方法
int executeUpdate()
ResultSet executeQuery()
3.使用预处理对象(PreparedStatement)实现查询操作
public class Test02 {
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 conn = JDBCUtils.getConn();
String sql = "select * from user where username = ? and password = ?";
//4.获取执行平台
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,username);
pst.setObject(2,password);
//5.执行sql
ResultSet rs = pst.executeQuery();
//6.处理结果集
if (rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//8.关闭资源
JDBCUtils.close(conn,pst,rs);
}
}
不使用PreparedStatement时:
select * from user where username = '柳岩' and password = '345' or '1' = '1'
使用PreparedStatement时:
select * from user where username = '柳岩' and password = '345\' or \'1\' = \'1'
经过PreparedStatement一处理,中间所有输入的' 都会变成普通的字符内容,mysql会认为345\' or \'1\' = \'都是密码内容,所以登录不上
/**
* 添加功能
*/
@Test
public void add()throws Exception{
//获取连接
Connection conn = JDBCUtils.getConn();
//准备sql
String sql = "insert into user(username,password) values (?,?)";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"杨幂");
pst.setObject(2,"9999");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils.close(conn,pst,null);
}
/**
* 删除功能
*/
@Test
public void delete()throws Exception{
//获取连接
Connection conn = JDBCUtils.getConn();
//准备sql
String sql = "delete from user where uid = ?";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"1");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils.close(conn,pst,null);
}
/**
* 修改功能
*/
@Test
public void update()throws Exception{
//获取连接
Connection conn = JDBCUtils.getConn();
//准备sql
String sql = "update user set password = ? where username = ?";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"0000");
pst.setObject(2,"有菜");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils.close(conn,pst,null);
}
/**
* 查询功能
*/
@Test
public void query()throws Exception{
//获取连接
Connection conn = JDBCUtils.getConn();
//准备sql
String sql = "select * from user";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//执行sql
ResultSet rs = pst.executeQuery();
//处理结果集
while(rs.next()){
Object uid = rs.getObject("uid");
Object username = rs.getObject("username");
Object password = rs.getObject("password");
System.out.println(uid+"..."+username+"..."+password);
}
//关闭资源
JDBCUtils.close(conn,pst,rs);
}
第五章.Properties集合使用回顾
1.Properties配合xxx.properties文件使用
2.我们需要将properties配置文件放到src下或者resources资源包下(开发常用的)
3.properties配置文件写法:
a.key=value形式
b.key和value默认都是String,但是不要加""
c.不要有空格
d.每个键值对写完,需要换行再写其他的键值对
public class Test04_Properties {
@Test
public void test01()throws Exception{
Properties properties = new Properties();
//利用类加载器读取配置文件
InputStream in =
Test04_Properties.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(in);
Set<String> set = properties.stringPropertyNames();
for (String key : set) {
String value = properties.getProperty(key);
System.out.println(value);
}
}
}
第六章.改造JDBC工具类_结合Properties文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/220227_java3?serverTimezone=UTC&rewriteBatchedStatements=true
username=root
password=root
/*
读取配置文件方式的工具类
*/
public class JDBCUtils2 {
private static String url;
private static String name;
private static String password;
/*
由于注册驱动和初始化url username password参数
应该最先执行,而且只执行一次即可
所以我们应该把这些代码放到静态代码块中
*/
static {
//注册驱动
try {
//创建Properties集合
Properties properties = new Properties();
//读取配置文件
InputStream in = JDBCUtils2.class.getClassLoader().getResourceAsStream("jdbc.properties");
//调用load方法,将流中的数据加载到集合中
properties.load(in);
//获取Properties集合职工的数据
String driver = properties.getProperty("driver");
Class.forName(driver);
url = properties.getProperty("url");
name = properties.getProperty("username");
password = properties.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConn() {
Connection connection = null;
try {
connection = DriverManager.getConnection(url, name, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 关闭资源
*/
public static void close(Connection connection, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class Test05 {
/**
* 添加功能
*/
@Test
public void add()throws Exception{
//获取连接
Connection conn = JDBCUtils2.getConn();
//准备sql
String sql = "insert into user(username,password) values (?,?)";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"明步");
pst.setObject(2,"1234");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils2.close(conn,pst,null);
}
/**
* 删除功能
*/
@Test
public void delete()throws Exception{
//获取连接
Connection conn = JDBCUtils2.getConn();
//准备sql
String sql = "delete from user where uid = ?";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"6");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils2.close(conn,pst,null);
}
/**
* 修改功能
*/
@Test
public void update()throws Exception{
//获取连接
Connection conn = JDBCUtils2.getConn();
//准备sql
String sql = "update user set password = ? where username = ?";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//为?赋值
pst.setObject(1,"0000");
pst.setObject(2,"明步");
//执行sql
int i = pst.executeUpdate();
//关闭资源
JDBCUtils2.close(conn,pst,null);
}
/**
* 查询功能
*/
@Test
public void query()throws Exception{
//获取连接
Connection conn = JDBCUtils2.getConn();
//准备sql
String sql = "select * from user";
//获取执行平台_预处理对象
PreparedStatement pst = conn.prepareStatement(sql);
//执行sql
ResultSet rs = pst.executeQuery();
//处理结果集
while(rs.next()){
Object uid = rs.getObject("uid");
Object username = rs.getObject("username");
Object password = rs.getObject("password");
System.out.println(uid+"..."+username+"..."+password);
}
//关闭资源
JDBCUtils2.close(conn,pst,rs);
}
}