数据库
数据库基础
1.什么是数据库
数据库是一种储存结构,他允许使用各种格式输入、处理和检索数据,不必在每次需要数据时重新输入。
特点:
- 实现数据共享。所有用户可以在数据库中同时存取数据。
- 减少数据的冗余度。
- 数据的独立性。包括数据库中数据库的逻辑结构和应用程序相互独立,包括数据的物理结构的变化不影响数据的逻辑结构
- 数据实现集中控制。
- 数据的一致性和可维护性以确保数据的安全性和可靠性。
其中包括:
- 安全性控制,防止数据丢失、错误更新和越权使用。
- 完整性控制,保证数据的正确性、有效性和相容性。
- 并发控制,在同一时间周期内允许对数据进行多路存取,又能防止用户之间的不正常交互
- 故障的发现和恢复
数据库的基本结构的三个层次:
- 物理数据层:是数据库的最内层,是物理存储设备上实际存储的数据集合。这些数据是原始数据,是用户加工的对象,由内部模式描述的指令操作处理的字符和字组成。
- 概念数据层:它是数据库的中间一层,是数据库的整体逻辑表示,指出了每个数据的逻辑定义及数据间的逻辑联系,是存储记录的集合。它所涉及的是数据库所有对象的逻辑关系,而不是它们的物理情况,是数据库管理员概念下的数据库。
- 逻辑数据层:它是用户所看到和使用的数据库,是一个或一些特定用户使用的数据集合,即逻辑记录的集合。
2.数据库的种类及功能
数据库系统一般基于某种数据模型,可以分为层次型、网状型、关系型及面向对象型等,简述如下:
-
层次型数据库:层次型数据库类似于树结构,是一组通过链接而相互联系在一起的记录。层次模型的特点是记录之间的联系通过指针实现。由于层次模型的层次顺序严格而且复杂,因此对数据进行各项操作都很困难。层次型数据库。
如图:
-
网状型数据库:网络模型是使用网络结构表示实体类型、实体间联系的数据模型。网络模型容易实现多对多的联系。但在编写应用程序时,程序员必须熟悉数据库的逻辑结构。
如图:
-
面向对象型数据库:建立在面向对象模型基础上。
-
关系型数据库:关系型数据库是目前最流行的数据库,是基于关系模型建立的数据库,关系模型是由一系列表格组成的。
3.SQL语言
SQL(结构化查询语言)被广泛地应用于大多数数据库中,使用SQL语句可以方便地查询、操作、定义和控制数据库中的数据。
SQL语言的主要组成部分:
- 数据定义语言(DDL)
- 数据操纵语言(DML)
- 数据控制语言(DCL)
- 事务控制语言(TCL)
其中在应用程序中使用最多的是数据操纵语言,是最常用的核心SQL语言
- select语句:用于从数据表中检索数据
语法:
SELECT 所选字段列表 FROM 数据表名
WHERE 条件表达式 GROUP BY 字段名 HAVING 条件表达式(指定分组的条件)
ORDER BY 字段名[ASC[DESC]]
- insert语句:用于插入新数据
INSERT INTO 表名[(字段名)] VALUES(属性值)
- update语句:用于更新数据表中的记录
UPDATE 数据表名 SET 字段名 = 新的字段值 WHERE 条件表达式
- delete语句:用于删除数据
DELETE FROM 数据表名 WHERE 条件表达式
JDBC
应用API接口达到使用Java语言来操控数据库的技术
JDBC导入
下载JDBC驱动jar包
jar包的下载官网地址:https://dev.mysql.com/downloads/connector/j/
数据库版本查询
1.win+R 打开cmd
2.登录
3.输入语句
SELECT VERSION();
其中8.0.17就是我的数据库版本
选择对应你下载的数据库版本
Operating System选择Platform independent,找到zip压缩包下载(使用迅雷直接进行外链接下载速度比较快)
进行解压
打开idea右击你的一个总工程包
进行导入路径
注意:导入的是解压后里面的jar包
最后你会看到:
说明导入成功
JDBC中常用的类和接口
位置:java.sql包
DriverManager类
作用:
作为JDBC的管理层,进行管理数据库中的驱动程序
操作数据库前,需要用Class类中的forName方法进行驱动:
MySQL数据库版本8.0以上
try{
//加载MySQL8.0以上数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
}catch(Exception e){
e.printStackTrace();
}
MySQL数据库版本5.X
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(Exception e){
e.printStackTrace();
}
DriverManager类常用方法
方法 | 说明 |
---|---|
getConnection(String url,String user,String password) | 指定3个入口参数(依次是连接数据库URL,用户名,密码)来获取与数据库的连接 |
setLoginTimeout() | 获取驱动程序试图登录到某一数据库时可以等待的最长时间,以秒为单位 |
println(String message) | 将一条消息打印到的当前的JDBC日志流中 |
连接本地MySQL数据库
数据库版本5.X版本:
Class.forName("com.mysql.jdbc.Driver");
DriverManager.getConnection("jdbc:mysql://IP地址:3306/数据库名","用户名","密码");
数据库版本8.0以上:
Class.forName("com.mysql.jdbc.cj.Driver");
DriverManager.getConnection("jdbc:mysql://IP地址:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true","用户名","密码");
其中3306是MySQL的默认端口
use Unicode用来启动Unicode字符集
characterEncoding指定字符集为UTF-8
useSSL指明不启动SSL连接
serverTimezone将时区定位中国
zeroDateTimeBehavior让空的日期数据以null形式返回
allowPublicKeyRetrieval允许客户端从服务器获取公钥
Connection接口
用途:与特定的数据库连接执行sql语句并返回结果
Connection接口常用方法
方法 | 说明 |
---|---|
createStatement() | 创建Statement对象 |
createStatement(int resultSetType,int resultSetConcurrency) | 创建一个Statement对象,该对象将生成具有给定类型、并发性和可保存性的ResultSet对象 |
preparedStatement() | 创建预处理对象preparedStatement |
isReadOnly() | 查看当前Connection对象的读取模式是否为只读形式 |
setReadOnly() | 设置当前Connection对象的读写模式,默认是非只读模式 |
commit() | 使所有上一次提交/回滚后进行的更改成为持久更改,并释放此Connection对象当前持有的所有数据库锁 |
roolback() | 取消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁 |
close() | 立即释放此Connection对象的数据库和JDBC资源,而不是等待它们被自动释放 |
Statement接口
用途:在已经连接的基础上向数据库发送sql语句
三种Statement对象:
- Statement:用于执行不带参数的简单sql语句
- PreparedStatement:继承Statement,用于执行动态sql语句
- CallableStatement:继承PreparedStatement,用于执行对数据库的存储过程的调用
Statement常用方法
方法 | 说明 |
---|---|
execute(String sql) | 执行静态的SELECT语句,该语句可能返回多个结果集 |
executeQuery(String sql) | 执行给定的SQL语句,该语句返回单个ResultSet对象 |
clearBatch() | 清空此 Statement对象的当前SQL命令列表 |
executeBatch() | 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的 |
addBatch(String sql) | 将给定的SQL命令添加到此 Statemcnt对象的当前命令列表中。如果驱动程序不支持批量处理,将抛出异常 |
close() | 释放 Statement实例占用的数据库和JDBC资源 |
PreparedStatement常用方法
方法 | 说明 |
---|---|
setInt(int index,int k) | 将指定位置的参数设置为int值 |
setFloat(int index,flaot f) | 将指定位置的参数设置为float值 |
setLong(int index,long l) | 将指定位置的参数设置为long值 |
setDouble(int index,double d) | 将指定位置的参数设置为double值 |
setBoolean(int index,boolean b) | 将指定位置的参数设置为boolean值 |
setDate(int index,date date) | 将指定位置的参数设置为对应的date值 |
executeQuery() | 在此 PreparedStatement对象中执行SOL查询,并返回该查询生成的ResultSet对象 |
setString(int index,String s) | 将指定位置的参数设置为对应的 String值 |
setNull(int index,intsqlType) | 将指定位置的参数设置为SOL NULL |
executeUpdate() | 执行前面包含的参数的动态INSERT.UPDATE或DELETE语句 |
clearParameters() | 清除当前所有参数的值 |
ResultSet接口
用途:ResultSet接口类似于一个临时表,暂时存放数据库查询操作所获得的结果集
实例具有指向当前数据行的指针,通过next()方法进行指针下移
ResultSet接口的常用方法
方法 | 说明 |
---|---|
getInt() | 以int形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为0 |
getFloat() | 以float形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为0 |
getDate() | 以date形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为null |
getBoolean() | 以boolean形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为null |
getString() | 以String形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为null |
getObject() | 以Object形式获取此ResultSet对象的当前行的指定列值,如果列值为null,则返回值为null |
first() | 将指针移动到当前记录的第一行 |
last() | 将指针移动到当前记录的最后一行 |
next() | 将指针向下移动一行 |
beforeFirst() | 将指针移动到集合的开头(第一行) |
afterLast() | 将指针移动到集合的尾部(最后一行) |
absolute(int index) | 将指针移动到ResultSet给定编号的行 |
isFirst() | 判断指针是否位于当前ResultSet集合的第一行,返回布尔值 |
isLast() | 判断指针是否位于当前ResultSet集合的最后一行,返回布尔值 |
updateInt() | 用int值更新指定列 |
updateFloat() | 用float值更新指定列 |
updateLong() | 用long值更新指定列 |
updateString() | 用string值更新指定列 |
updateObject() | 用Object值更新指定列 |
updateNull() | 将指定的列值修改为null |
updateDate() | 用date值更新指定列 |
updateDouble() | 用double值更新指定列 |
getrow() | 查看当前行的索引号 |
insertRow() | 将插入行的内容插入数据库 |
updateRow() | 将当前行的内容同步到数据表 |
deleteRow() | 删除当前行,但并不同步到数据库中,而是在执行close()方法后同步到数据库 |
数据库操作
连接数据库
要访问数据库首先要加载数据库的驱动程序,只需要第一次访问数据库时加载一次即可,然后每次访问数据时创建一个Connection对象,然后执行sql语句最后完成后摧毁前面的对象释放与数据库的连接。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC_Demo1 {
public static void main(String[] args) throws Exception{
//1.导入驱动jar包
//2.注册驱动
/*MySQL8.0版本需要更换驱动为“com.mysql.cj.jdbc.Driver”
之前的“com.mysql.jdbc.Driver”已经不能在MySQL 8.0版本使用了。
然后将url改成:
DriverManager.getConnection("jdbc:mysql://IP地址:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true","用户名","密码") 即可
简写:jdbc:mysql://localhost:3306/syf?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false*/
//Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取数据库连接对象
//Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/syf?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false","root","syf20020816");
//4.定义sql语句
//String sql = "SELECT*FROM stu4";
//5.获取执行sql的对象Statement
//Statement stmt = cn.createStatement();
//6.执行sql语句
//int count = stmt.executeUpdate(sql);
//7.处理结果
//System.out.println(count);
//8.释放资源
//stmt.close();
//cn.close();
Connection cn = null;//声明数据库连接对象
try{
//加载MySQL数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
cn = DriverManager.getConnection("jdbc:mysql://:3306/syf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true","root","******");
}catch(SQLException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
if (cn != null){
System.out.println("数据库连接成功");
System.out.println(cn);
}
}
}
向数据库发送SQL语句
我们要创建statement对象来执行sql语句
使用Connection类创建的cn对象的createStatement()方法可以获得Statement对象
Connection cn = DriverManager.getConnection("url","user","pwd");
Statement stmt = cn.createStatement();
处理查询结果
ResultSet类的对象可以存放查询的结果集,一次只能看到一行数据使用next()方法将光标下移
ResultSet res = stmt.executeQuery("SELECT * FROM stu4");
顺序查询
import java.sql.*;
public class JDBC_Demo2 {
public static void main(String[] args) {
try{
Class.forName("com.mysql.cj.jdbc.Driver");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
Connection cn = DriverManager.getConnection("jdbc:mysql://:3306/syf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true","root","******");
Statement stm = cn.createStatement();
ResultSet result = stm.executeQuery("SELECT * FROM stu4");
while (result.next()){
String id = result.getString("id");
String name = result.getString("name");
System.out.print("id"+id+"\t");
System.out.println("name"+name);
}
cn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
模糊查询
SQL语句中提供了LIKE用于模糊查询,使用%来代替0个或多个字符,使用_来代替字符
预处理语句
通过Connection对象的preparedStatement方法对sql语句进行预处理,生成数据库底层的内部命令,并且将该命令封装在preparedStatement对象中,通过调用该对象的相应方法,可执行底层数据库命令。
即:应用程序能针对连接的数据库,将SQL语句解释为数据库底层的内部命令,然后让数据库执行这个命令。这样可以减轻数据库的负担,提高访问速度。
对SQL进行预处理时可以用?来代替任何字段值:
sql = cn.prepareStatement("SELECT * FROM stu4 WHERE id = ?");
在执行预处理语句前,必须用相应方法来设置通配符所表示的值:
sql.setInt(1,16);
其中
1:从左向右的第一个通配符
16:表示设置的通配符的值
将通配符的值设为16上面的两行代码就equal:
sql = cn.prepareStatement("SELECT * FROM stu4 WHERE id = 16")
添加,修改,删除
通过使用PreparedStatement类的指定参数,动态地对数据表进行修改,通过executeUpdate()方法执行更新语句操作。