MySQL
初识MySQL
什么是数据库?为什么要学数据库?
为什么学习数据库
- 岗位需求
- 大数据时代~
- 被迫需求:存数据
- 数据库是所有软件体系中最核心的存在 DBA
什么是数据库
-
数据库(DB,DataBase)
-
概念:数据仓库,软件,安装在操作系统上(Windonw、Linux、Mac)之上! SQL
-
作用:存数据,管理数据
关系型数据库和非关系型数据库区别
关系型数据库:(SQL)
- MySQL,Oracle,sql Server,DB2,SQLlite
- 通过表和表之间,行和列之间的关系进行数据的存储
非关系型数据库:(NoSQL)Not Only
- Redis,MongDB
- 非关系型数据库,对象存储,通过对象的自身的属性来决定。
DBMS(数据库管理系统)
- 数据库的管理软件,科学有效的管理我们的数据.维护和获取数据;
- MySQL,数据库管理系统
MySQL简介
MySQL是一个关系型数据库管理系统
MySQL是最好的RDBMS(关系型数据库)应用软件之一
开源的数据库软件
体积小,速度快,总体拥有成本低,招人成本低,所有人必须会~
中小型网站,或者大型网站,集群!
连接数据库
命令行连接!
mysql -uroot -proot --连接数据库
-- 所有的语句都使用;结尾
show databases; --查看所有的数据库
mysql> use school --切换数据库 use 数据库名
Database changed
show tables; --查看数据库中所有的表
desc student; --显示数据库中所有表的信息
create database westos; --创建一个数据库
数据库xxx语言
DDL 定义
DML 操作
DQL 查询
DCL 控制
操作数据库( 了解 )
操作数据库 > 操作数据库中的数据 > 操作数据库中表的数据
mysql 不区分大小写
操作数据库
- 创建数据库
create database westos;
- 删除数据库
drop database westos;
- 使用数据库
use `school`
- 查看数据库
show databases; --查看所有的数据库
数据库的列类型
数值
- tinyint 十分小的数据 1个字节
- smallint 较小的数据 2个字节
- int 标准的整数 4个字节 ★
- bigint 较大的数据 8个字节
- float 浮点数 4个字节
- double 浮点数 8个字节 ( 精度问题 ! )
- decimal 字符串形式的浮点数 一般金融计算的时候使用
字符串
- char 字符串 0~255
- varchar 可变字符串 0~65535 常用的变量
- tinytext 微型文本 2^8 -1
- text 文本串 2^16 -1 保存大文本
时间日期
java.util.Date
- date YYYY-MM-DD 日期格式
- time HH:mm:ss 时间格式
- datetime YYYY-MM-DD HH:mm:ss 最常用的时间格式
- timestamp 时间戳, 1970.1.1 到现在的毫秒数 ! 也较为常用
- year 年份表示
null
- 没有值
- 注意,不要使用NULL进行运算,结果为NULL
数据库的字段属性 ( 重点 )
无符号:
- 无符号的整数
- 声明了该列不能声明为负数
零填充:
- 不足的位数,使用0来填充 int ( 3 ) 5 --- 005
自动递增
- 通常理解为自增,自动在上一条记录的基础上 + 1(默认)
- 通常用来设计唯一的主键~ index
- 可以自定义设计主键自增的起始值和步长
非空 NULL not null
- 假设设置为 not null ,如果不给它赋值,就会报错 !
- NULL , 如果不填写值 , 默认就是null !
默认
- 设置默认的值
- sex , 默认值为男, 如果不指定该列的值 则会有默认的值 !
创建数据库表 ( 重点 )
-- 目标 : 创建一个school数据库
-- 创建学生表(列,字段) 使用SQL 创建
-- 学号int 登录密码varchar(20) 姓名性别varchar(2),出生日期,家庭住址
-- 注意点,使用英文() 表的 名称 和 字段 尽量用 ` ` 括起来
-- AUTO_INCREMENT 自增
-- 字符串使用 单引号括起来!
-- 所有语句后面加 , 最后一个不用加
-- PRIMARY KEY 主键,一般一个表只有一个唯一的主键
CREATE TABLE `student` (
`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` varchar(2) NOT NULL DEFAULT '女' COMMENT '性别',
`birthday` datetime DEFAULT NULL COMMENT '出生日期',
`address` varchar(100) DEFAULT NULL COMMENT '家庭住址',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
格式
CREATE TABLE [IF NOT EXISTS] `表名`(
'字段名' 列类型 [属性] [索引] [注释],
'字段名' 列类型 [属性] [索引] [注释],
......
'字段名' 列类型 [属性] [索引] [注释],
)
修改删除表
修改
-- ALTER TABLE 旧表名 RENAME AS 新表名
ALTER TABLE student RENAME AS student1
-- 增加表的字段 ALTER TABLE 表名 ADD 字段名 列属性
ALTER TABLE studen1 ADD age INT(11)
-- 修改表的字段(重命名,修改约束!)
-- ALTER TABLE 表名 MODIFY 字段名 列属性[]
ALTER TABLE student1 MODIFY id VARCHAR(11) -- 修改约束
-- ALTER TABLE 表名 CHANGE 旧名字 新名字 列属性[]
ALTER TABLE student1 CHANGE id id1 INT(11) -- 字段重命名
-- 删除表的字段: ALTER TABLE 表名 DROP 字段名
ALTER TABLE student1 DROP id1
删除
-- 删除表(如果表存在再删除)
DROP TABLE IF EXISTS studen1
所有的创建和删除操作尽量加上判断
注意点:
`` 字段名,用这个包裹- 注释: -- /**/
- sql 关键字大小写不敏感,建议写小写
- 所有的符号用英文
MySQL数据管理
外键(了解即可)
DML语言(全部记住)
数据库意义: 数据存储,数据管理
DML语言: 数据操作语言
添加( Insert )
-- 插入语句(添加)
-- insert into 表名([字段名1,字段2,字段3]values('值1'),('值2'),(值3,....)
INSERT INTO `grade` (`gradeid`) VALUES('1')
-- 一般写插入语句,我们一定要数据和字段一一对应!
-- 插入多个字段
INSERT INTO `grade` (`gradeid`,`gradename`) VALUES('2','张三')
INSERT INTO `grade` (`gradeid`,`gradename`)
VALUES('3','李四'),('4','王五')
语法:insert into 表名([字段名1,字段2,字段3]values('值1'),('值2'),(值3,....)
注意事项:
- 字段和字段之间使用英文逗号隔开
- 字段是可以省略的,但是后面的值必须要一一对应,不能少
- 可以同时插入多条数据,VALUES后面的值,需要用,隔开即可
修改( update )
-- 修改学员名字,带了条件
UPDATE `student` SET `name`='狂神' WHERE id=1;
-- 不指定条件的情况下,会改动所有表! (小心删库跑路)
UPDATE `student` SET `name`='长江七号'
-- 修改多个属性
UPDATE `student` SET `name`='南子旭',`email`='766656302@qq.com' WHERE id=1;
-- 语法:
-- 修改多个属性
-- UPDATE 表名 SET colnum_name = value,[colnum_name = value,....] WHERE [条件];
条件: where 子句 运算符 id等于某个值
操作符返回布尔值
| 操作符 | 含义 | 范围 | 结果 |
|---|---|---|---|
| = | 等于 | 5=6 | false |
| <> 或 != | 不等于 | 5<>6 | true |
| > | |||
| < | |||
| >= | |||
| <= | |||
| BETWEEN ... AND ... | 在某个范围内 | [2,5] | |
| AND | 和 && | 5>1 and 1>2 | false |
| OR | 或 || | 5>1 or 1>2 | true |
-- 通过多个条件定位数据
UPDATE `student` SET `name`='迪迦' WHERE `name`='南子旭' AND `sex`='男'
语法:UPDATE 表名 SET colnum_name = value,[colnum_name = value,....] WHERE [条件];
注意:
- colnum_name 是数据库的列,尽量带上 ``
- 条件,筛选的条件,如果没有指定,则会修改所有的列
- value,是一个具体的值,也可以是一个变量
-- 设置时间为当前时间
UPDATE `student` SET `birthday`=CURRENT_TIME WHERE `name`='南子旭' AND `sex`='男'
删除( delete )
语法:DELETE FROM 表名 [WHERE 条件];
-- 删除数据(避免这样写,会全部删除)
DELETE FROM `student`
-- 删除指定数据
DELETE FROM `student` WHERE id=4;
TRUNCATE 命令
作用: 完全清空一个数据库表,表的结构和索引约束不会变 !
-- 清空 student 表
TRUNCATE `student`
delete 和 TRUNCATE 区别
- 相同点:都能删除数据,都不会删除表结构
- 不同:
- TRUNCATE 重新设置 自增列 计数器会归零
- TRUNCATE 不会影响事务
DELETE FROM `student` -- 不会影响自增
TRUNCATE `student` -- 自增会归零
DQL查询数据( 最重点 )★
(Data Query Language: 数据查询语言)
- 所有的查询操作都用它 Select
- 简单的查询,复杂的查询它都能做~
- 数据库中最核心的语言,最重要的语句
- 使用频率最高的语句
SELECT完整语法
SELECT [ALL | DISTINCT]
{* | TABLE.* |[TABLE.field1[AS alias1][,TABLE.field2[AS alias2]][,...]]}
FROM TABLE_name [as TABLE_alias]
[LEFT | RIGHT | INNER JOIN TABLE_name2] -- 联合查询
[WHERE ...] -- 指定结果需满足条件
[GROUP BY ...] -- 指定结果按照哪几个字段来分组
[HAVING] -- 过滤分组的记录必须满足的必要条件
[ORDER BY] -- 指定查询记录按照一个或多个条件排序
[LIMIT {[OFFSET,]ROW_COUNT | ROW_COUNTOFFSET OFFSET}];
-- 指定查询的记录从哪条至哪条
注意:[]代表可选的,{}代表必选
指定查询字段
-- 查询全部学生的信息 SELECT 字段 FROM 表
SELECT * FROM student
-- 查询指定字段
SELECT `id`,`name` FROM student
-- 别名:给结果起一个名字 AS
SELECT `id` AS 学号,`name` AS 姓名 FROM student
-- 函数Concat (a,b)
SELECT CONCAT('姓名',name) AS 新名字 FROM student
字段:SELECT 字段... FROM 表
有时候,列名字不是那么的见名知意. 我们起别名 AS 字段名 AS 别名 表名 AS 别名
去重 distinct
作用:去除SELECT查询出来的结果中重复的数据,只显示一条
SELECT DISTINCT `name` FROM `student` -- 发现重复数据,去重
数据库的列 ( 表达式 )
-- 考试成绩加一分查看
SELECT `id`,`score`+1 AS '加分后' FROM student
SELECT 100*3-1 AS '计算结果' -- 用来计算
数据库中的表达式: 文本值,列,Null,函数,计算表达式,系统变量....
SELECT 表达式 FROM 表
where 条件子句
作用:检索数据中符合条件的值
搜索的条件由一个或多个表达式组成! 结果 布尔值
逻辑运算符
| 运算符 | 语法 | 描述 |
|---|---|---|
| and && | a and b a && b | 逻辑与,两个都为真,结果为真 |
| or || | a or b a || b | 逻辑或,其中一个为真,结果为真 |
| Not ! | not a ! a | 逻辑非,真假假真! |
尽量使用英文字母
-- 查询分数在 95-150 之间
SELECT id ,`score` FROM student
WHERE score>=95 AND score<=150
-- 模糊查询(区间)
SELECT id ,`score` FROM student
WHERE score BETWEEN 95 AND 150
-- 查询除了1号之外的学生分数
SELECT id ,`score` FROM student
WHERE id!=1
SELECT id ,`score` FROM student
WHERE NOT id=1
模糊查询 : 比较运算符
| 运算符 | 语法 | 描述 |
|---|---|---|
| IS NULL | a is null | 如果操作符为null,结果为真 |
| IS NOT NULL | a is not null | 如果操作符为 not null,结果为真 |
| BETWEEN | a between b and c | 若 a 在 b 和 c 之间,则结果为真 |
| Like | a like b | SQL匹配,如果a匹配b,则结果为真 |
| IN | a IN (a1,a2,a3......) | 假设a在a1,或者a2.....其中的某一个值中,结果为真 |
-- 查询姓张的同学
-- LIKE结合 %(代表0到任意个字符) _(一个字符)
SELECT `id`,`name` FROM student
WHERE name LIKE '张%'
-- 查询姓张的同学,名字只有两位的
SELECT `id`,`name` FROM student
WHERE name LIKE '张_'
-- 查询姓张的同学,名字只有三位的
SELECT `id`,`name` FROM student
WHERE name LIKE '张__'
-- 查询名字中间有子字的同学 %子%
SELECT `id`,`name` FROM student
WHERE name LIKE '%子%'
-- ===========IN==========
-- 查询指定的学生
SELECT `id`,`name` FROM student
WHERE id in (1,2,3)
-- 查询在北京的学生
SELECT `id`,`name` FROM student
WHERE `address` in ('北京','漯河');
-- ========null not null===
-- 查询地址为空的学生
SELECT `id`,`name` FROM student
WHERE address='' or address is NULL ;
-- 查询有出生日期的同学 (不为空)
SELECT `id`,`name` FROM student
WHERE birthday is not NULL
-- 查询没有出生日期的同学
SELECT `id`,`name` FROM student
WHERE birthday is NULL
联表查询 待学*
分页查询和排序
排序
-- ========== 分页 LIMIT 和排序 ORDER BY===========
-- 排序: 升序 ASC , 降序 DESC
-- ORDER BY 通过哪个字段排序
-- 查询的结果根据 成绩降序 排序
SELECT `id`,`name`,`score`
FROM student
ORDER BY score DESC
分页
-- ========== 分页 LIMIT 和排序 ORDER BY===========
-- 排序: 升序 ASC , 降序 DESC
-- ORDER BY 通过哪个字段排序
-- 查询的结果根据 成绩降序 排序
SELECT `id`,`name`,`score`
FROM student
ORDER BY score DESC
-- 为什么要分页
-- 缓解数据库压力,给人的体验更好
-- 分页,每页只显示五条数据
-- 语法: LIMIT 当前页,页面的大小
-- 第一页 LIMIT 0,5 (1-1)*5
-- 第二页 LIMIT 5,5 (2-1)*5
-- 第三页 LIMIT 10,5 (3-1)*5
-- 第N页 LIMIT 0,5 (n-1)*pageSize,pageSize
-- [pageSize:页面大小]
-- [(n-1)*pageSize起始值]
-- [n:当前页]
-- [数据总数/页面大小 = 总页数]
SELECT `id`,`name`,`score`
FROM student
LIMIT 5,5
语法:LIMIT(查询起始下标,pageSize)
子查询 待学*
本质:在where语句中嵌套一个子查询语句
MySQL函数
常用函数
聚合函数(常用)
事务
索引
权限管理和备份
规范数据库设计
JDBC(重点)
数据库驱动
JDBC
SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,俗称JDBC
第一个JDBC程序
1.创建测试数据库
CREATE TABLE `student` (
`id` int(5) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` varchar(2) NOT NULL DEFAULT '女' COMMENT '性别',
`birthday` datetime DEFAULT NULL COMMENT '出生日期',
`address` varchar(100) DEFAULT NULL COMMENT '家庭住址',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`score` int(5) DEFAULT NULL COMMENT '分数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES (1, '迪迦', '1234', '男', '2020-12-14 00:00:00', '郑州市', '766656302@qq.com', 60);
INSERT INTO `student` VALUES (2, '曾小贤', '123456', '女', '2020-12-16 14:51:38', '北京', NULL, 70);
INSERT INTO `student` VALUES (3, '吕小布', '123456', '女', '2020-12-01 14:51:43', '武汉', NULL, 80);
INSERT INTO `student` VALUES (4, '斯内克', '123456', '女', NULL, '杭州', NULL, 100);
INSERT INTO `student` VALUES (5, '南子旭', '123456', '女', NULL, '上海', NULL, 140);
INSERT INTO `student` VALUES (6, '张三', '123456', '女', NULL, '广州', NULL, 100);
INSERT INTO `student` VALUES (7, '张大炮', '123456', '女', NULL, '漯河', NULL, 100);
INSERT INTO `student` VALUES (8, '匿名', '123456', '女', NULL, '广西', NULL, 100);
INSERT INTO `student` VALUES (9, '匿名', '123456', '女', NULL, '洛阳', NULL, 100);
INSERT INTO `student` VALUES (10, '匿名', '123456', '女', NULL, NULL, NULL, 100);
INSERT INTO `student` VALUES (11, '匿名', '123456', '女', NULL, NULL, NULL, NULL);
INSERT INTO `student` VALUES (12, '南子旭', '123456', '男', NULL, NULL, NULL, NULL);
2.导入jar包
3.编写测试代码
package com.soft.test;
import java.sql.*;
public class TestStudent {
public static void main(String[] args) {
ResultSet resultSet = null;
Connection con = null;
Statement stmt = null;
try {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.用户信息和url
String url = "jdbc:mysql://localhost:3306/school?serverTimezone=GMT";
String userName = "root";
String pwd = "root";
//3.连接成功,数据库对象 Connection 代表数据库
con = DriverManager.getConnection(url, userName, pwd);
//4.执行SQL的对象 Statement
stmt = con.createStatement();
//5.执行SQK的对象去执行SQL
String sql = "insert into student(name,pwd,sex) values('南子旭','123456','男')";
String sql1 = "SELECT * FROM student";
// int i = stmt.executeUpdate(sql);
// if (i == 1){
// System.out.println("添加成功!");
// }else {
// System.out.println("添加失败!");
// }
resultSet = stmt.executeQuery(sql1); //executeQuery返回一个结果集,结果集中封装了我们全部的查询结果
System.out.println(resultSet);
while (resultSet.next()){
String name = resultSet.getString(1);
String name2 = resultSet.getString(2);
String name3 = resultSet.getString(3);
String name4 = resultSet.getString(4);
String name5 = resultSet.getString(5);
String name6 = resultSet.getString(6);
String name7 = resultSet.getString(7);
System.out.println(name+name2+name3+name4+name5+name6+name7);
}
} catch (ClassNotFoundException e) {
System.out.println("驱动加载失败!");
e.printStackTrace();
} catch (SQLException throwables) {
System.out.println("数据库连接失败!");
throwables.printStackTrace();
}finally {
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (con != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
步骤总结:
- 加载驱动
- 定义用户信息和url
- 连接数据库DriverManager.getConnection
- 获得执行sql对象 Statement
- 获得返回的结果集
- 释放连接
Statement对象
DriverManager
//加载驱动 固定写法
Class.forName("com.mysql.cj.jdbc.Driver");
URL
String url = "jdbc:mysql://localhost:3306/school?serverTimezone=GMT";
Statement 执行SQL的对象 PreparedStatement 执行SQL的对象
String sql1 = "SELECT * FROM student"; //创建SQL语句
Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate
和execute
1、ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句
,返回一个结果集(ResultSet)对象。
2、int executeUpdate(String sqlString):用于执行INSERT、UPDATE或
DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等
3、execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的
语句。
具体实现的代码:
ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ;
int rows = stmt.executeUpdate("INSERT INTO ...") ;
boolean flag = stmt.execute(String sql) ;
ResultSet
resultSet.getObject //在不知道类型的情况下使用
resultSet.getString //知道类型的情况下使用
resultSet.next() //移动到下一个数据
释放资源
resultSet.close();
resultSet.close();
resultSet.close();
代码实现
-
提取工具类
package com.soft.util; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.*; public class DbUtil { private static String driver = null; private static String url = null; private static String userName = null; private static String pwd = null; static Connection conn = null; static PreparedStatement stmt = null; static ResultSet rs = null; static { try { InputStream in = DbUtil.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(in); driver = properties.getProperty("driver"); url = properties.getProperty("url"); userName = properties.getProperty("userName"); pwd = properties.getProperty("pwd"); //1.驱动只用加载一次 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { System.err.println("驱动加载异常!"); e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, userName, pwd); } //释放资源 public static void release(Connection conn, Statement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } //封装增删改方法 public static void updateOrInsertOrDelete(String sql, Object... objs) { try { stmt = getConnection().prepareStatement(sql); int i = 1; for (Object obj : objs ) { stmt.setObject(i++, obj); } int m = stmt.executeUpdate(); if (m > 0) { System.out.println("操作成功!"); } else { System.out.println("操作失败!"); } } catch (SQLException throwables) { System.err.println("处理SQL出现异常!"); throwables.printStackTrace(); }finally { release(conn, stmt, rs); } } //封装查询方法 public static List<LinkedHashMap<String, String>> query(String sql, Object... objs) { List<LinkedHashMap<String, String>> list = null; LinkedHashMap<String, String> map = null; try { stmt = getConnection().prepareStatement(sql); int i = 1; for (Object obj : objs ) { stmt.setObject(i++, obj); } rs = stmt.executeQuery(); // while (rs.next()){ // for (int j = 1; j < objs.length; j++) { // System.out.println(rs.getString(j)); // } // } ResultSetMetaData metaData = rs.getMetaData(); // System.out.println(metaData); int count = metaData.getColumnCount(); list = new ArrayList<>(); while (rs.next()) { for (int j = 1; j <= count; j++) { map = new LinkedHashMap<>(); String columnName = metaData.getColumnName(j); String value = rs.getString(j); map.put(columnName, value); list.add(map); } } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { release(conn, stmt, rs); } return list; } }driver = com.mysql.cj.jdbc.Driver url = jdbc:mysql://localhost:3306/school?serverTimezone=GMT userName = root pwd = root -
增加方法
public class TestInsert {
public static void main(String[] args) {
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
try {
connection = DbUtil.getConnection(); //获取数据库连接
stmt = connection.createStatement(); //获得SQL的执行对象
String sql = "insert into student(name,pwd,sex) values('南子旭','123456','男')";
int i = stmt.executeUpdate(sql);
if (i > 0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DbUtil.release(connection,stmt,rs);
}
}
}
-
查询方法
public class TestSelect { public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn= DbUtil.getConnection(); stmt = conn.createStatement(); String sql = "SELECT * FROM student"; rs = stmt.executeQuery(sql); while (rs.next()){ System.out.println(rs.getString(1)); System.out.println(rs.getString(2)); System.out.println(rs.getString(3)); System.out.println(rs.getString(4)); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DbUtil.release(conn,stmt,rs); } } }
SQL注入问题
sql存在漏洞,会被攻击存在数据泄露,SQL会被拼接 or
package com.soft.test;
import com.soft.util.DbUtil;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Sql {
public static void main(String[] args) {
// login("迪迦","1234");
login("'or' 1=1","'or' 1=1");
}
public static void login(String name,String pwd){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn= DbUtil.getConnection();
stmt = conn.createStatement();
String sql = "SELECT * FROM student where name='"+name+"' and pwd ='"+pwd+"'";
rs = stmt.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString(1));
System.out.println(rs.getString(2));
System.out.println(rs.getString(3));
System.out.println(rs.getString(4));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DbUtil.release(conn,stmt,rs);
}
}
}
PreparedStatement对象
preparedStatement可以防止SQL注入,效率更高!
-
新增
package com.soft.test2; import com.soft.util.DbUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; public class TestInsert { public static void main(String[] args) { Connection conn = null; PreparedStatement stmt = null; try { conn = DbUtil.getConnection(); String sql = "insert into student(name,pwd,sex,birthday) values(?,?,?,?)"; stmt = conn.prepareStatement(sql); //手动给参数赋值 stmt.setString(1,"雷军"); stmt.setString(2,"123456"); stmt.setString(3,"男"); //注意点: sql.Date 数据库 java.sql.Date // util.Date Java new Date().getTime() 获得时间戳 stmt.setDate(4,new java.sql.Date(new Date().getTime())); //执行 int i = stmt.executeUpdate(); if (i > 0){ System.out.println("插入成功!"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DbUtil.release(conn,stmt,null); } } } -
删除
package com.soft.test2; import com.soft.util.DbUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; public class TestDelete { public static void main(String[] args) { Connection conn = null; PreparedStatement stmt = null; try { conn = DbUtil.getConnection(); String sql = "delete from student where id = ?"; stmt = conn.prepareStatement(sql); //手动给参数赋值 stmt.setInt(1,10); //执行 int i = stmt.executeUpdate(); if (i > 0){ System.out.println("删除成功!"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DbUtil.release(conn,stmt,null); } } } -
更新
package com.soft.test2; import com.soft.util.DbUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class TestUpdate { public static void main(String[] args) { Connection conn = null; PreparedStatement stmt = null; try { conn = DbUtil.getConnection(); String sql = "update student set name = ? where id=?;"; stmt = conn.prepareStatement(sql); //手动给参数赋值 stmt.setString(1, "南子旭"); stmt.setInt(2,10); //执行 int i = stmt.executeUpdate(); if (i > 0) { System.out.println("更新成功!"); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DbUtil.release(conn, stmt, null); } } } -
查询
package com.soft.test2; import com.soft.util.DbUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class TestSelect { public static void main(String[] args) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = DbUtil.getConnection(); String sql = "select * from student where id = ?;"; stmt = conn.prepareStatement(sql); stmt.setInt(1,1); //执行 rs = stmt.executeQuery(); if (rs.next()){ System.out.println(rs.getString(3)); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DbUtil.release(conn,stmt,rs); } } } -
防止SQL注入
package com.soft.test2;
import com.soft.util.DbUtil;
import java.sql.*;
public class Sql {
public static void main(String[] args) {
// login("迪迦","1234");
login("'' or 1=1","'' or 1=1");
}
public static void login(String name,String pwd){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn= DbUtil.getConnection();
//PreparedStatement 防止SQL注入的本质,把传递进来的参数当做字符
//假设其中存在转义字符,会被直接转义 比如'
String sql = "SELECT * FROM student where name = ? and pwd = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1,name);
stmt.setString(2,pwd);
rs = stmt.executeQuery();
while (rs.next()){
System.out.println(rs.getString(1));
System.out.println(rs.getString(2));
System.out.println(rs.getString(3));
System.out.println(rs.getString(4));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DbUtil.release(conn,stmt,rs);
}
}
}
使用IDEA连接数据库
连接成功后可以选择数据库

事务
要么都成功,要么都失败
ACID原则
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
- 隔离性的问题
- 脏读:一个事物读取了另一个没有提交的事务
- 不可重复读:在同一事务内,重复读取表中的数据,表数据发生了改变
- 虚度(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致
持久性:一单提交不可逆,持久化到数据库了
代码实现
- 开启事务
conn.setAutoCommit(false); - 一组业务执行完毕,提交事务
- 可以在catch语句中显示定义回滚语句,但默认失败就会回滚
package com.soft.test3;
import com.soft.util.DbUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn= DbUtil.getConnection();
//关闭数据库的自动提交功能
conn.setAutoCommit(false); // 开启事务
String sql1 = "update account set money = money - 100 where name = 'A';";
stmt = conn.prepareStatement(sql1);
stmt.executeUpdate();
// int x = 1/0;
String sql2 = "update account set money = money + 100 where name = 'B';";
stmt = conn.prepareStatement(sql2);
stmt.executeUpdate();
//业务完毕提交事务
conn.commit();
System.out.println("成功!");
} catch (SQLException throwables) {
// try {
// conn.rollback(); //如果失败则回滚事务
// } catch (SQLException e) {
// e.printStackTrace();
// }
throwables.printStackTrace();
}finally {
DbUtil.release(conn,stmt,rs);
}
}
}
数据库连接池
数据库连接 --- 执行完毕 --- 释放
连接 -- 释放 十分浪费系统资源
池化技术:准备一些预先的资源,过来就连接预先准备好的
最小连接数:
最大连接数:
等待超时:
编写连接池,实现一个接口 DataSource
开源数据源实现
DBCP
C3P0
Druid:阿里巴巴
使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!
BDCP
需要用到的jar包
commons-dbcp-1.4.jar
commons-pool2-2.9.0.jar

浙公网安备 33010602011771号