上传部分文档
This commit is contained in:
1 parent
6605a34b36
commit
e2921c8347
15 files changed
+346
-17
No files matched your search
@@ -0,0 +1,19 @@
|
||||
JDBC(Java Database Connectivity)
|
||||
是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
|
||||
|
||||
JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
|
||||
|
||||
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
|
||||
|
||||
如果没有JDBC,那么Java程序访问数据库时是这样的:
|
||||
|
||||

|
||||
|
||||
有了JDBC,Java程序访问数据库时是这样的:
|
||||
|
||||

|
||||
|
||||
总结如下:
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
JDBC接口(API)包括两个层次:
|
||||
|
||||
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
|
||||
|
||||
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
|
||||
|
||||
JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。
|
||||
|
||||
不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ——— 面向接口编程
|
||||
|
||||
JDBC程序编写步骤
|
||||
|
||||

|
||||
|
||||
补充:ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用者在程序中只需要调用ODBC API,由
|
||||
ODBC 驱动程序将调用转换成为对特定的数据库的调用请求。
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 连接步骤概述
|
||||
|
||||
第一步:注册驱动(作用告诉Java程序,即将要连接的数据库是哪个品牌的)
|
||||
|
||||
第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间通信,使用之后一定要关闭)
|
||||
|
||||
第三步:获取数据库操作对象(专门负责执行sql语句的对象)
|
||||
|
||||
第四步:执行SQL语句
|
||||
|
||||
第五步:处理查询结果集(只有当第四步指定的是select语句时,才会有第五步的查询结果集)
|
||||
|
||||
第六步:释放资源(使用完资源一定要释放)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
## 第一种方式
|
||||
|
||||
这种方式注册的驱动数据最原始的方式,不常用
|
||||
|
||||
```java
|
||||
Statement stmt = null;
|
||||
Connection conn = null;
|
||||
try {
|
||||
// 1、注册驱动
|
||||
DriverManager.registerDriver(new Driver());
|
||||
// 2、获取连接
|
||||
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "123456");
|
||||
System.out.println(conn);
|
||||
// 3、获取数据库操作对象
|
||||
// 这个方法创建的对象,是专门用来指定 sql 语句的
|
||||
stmt = conn.createStatement();
|
||||
// 4、执行 sql
|
||||
String sql1 = "insert into t_student(id, name, class) VALUE (9, '张三', 3)";
|
||||
// 这个方法用于执行 DML 语句(insert,update,delete),并且返回值是影响数据库中记录条数
|
||||
int count = stmt.executeUpdate(sql1);
|
||||
System.out.println(count);
|
||||
// 5、处理查询结果集
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
// 6、释放资源
|
||||
// 在这里确保数据内容一定要关闭
|
||||
if (stmt != null) {
|
||||
try {
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 获取连接的第二种方式
|
||||
在JDBC的Driver中静态代码快中已经写好了实现类,使用反射进行静态代码块的调用,完成连接的获取
|
||||
|
||||
这种方式更加常用
|
||||
```java
|
||||
try {
|
||||
// 使用反射机制运行这个类中的静态代码块,完成对应内容的获取
|
||||
/*
|
||||
Mysql的JDBC中的Driver的静态代码块
|
||||
static {
|
||||
try {
|
||||
java.sql.DriverManager.registerDriver(new Driver());
|
||||
} catch (SQLException E) {
|
||||
throw new RuntimeException("Can't register driver!");
|
||||
}
|
||||
}
|
||||
*/
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "123456");
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
```
|
||||
|
||||
## 获取连接的最终版
|
||||
以上连接的方式都是基于代码量的减少,为了让代码更灵活,往往会将需要配置的内容放到一个配置文件中,通过读取配置文件获取对应要操作的内容
|
||||
|
||||
这种方式更加灵活,也更加常用
|
||||
|
||||
```java
|
||||
// 使用 资源绑定器 获取配置文件中的内容
|
||||
ResourceBundle bundle = ResourceBundle.getBundle("JDBCTest04");
|
||||
String className = bundle.getString("className");
|
||||
String url = bundle.getString("url");
|
||||
String user = bundle.getString("user");
|
||||
String password = bundle.getString("password");
|
||||
String sql = bundle.getString("sql");
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
|
||||
try {
|
||||
// 注册驱动
|
||||
Class.forName(className);
|
||||
conn = DriverManager.getConnection(url, user, password);
|
||||
// 获取数据操作对象
|
||||
stmt = conn.createStatement();
|
||||
// 执行 sql 语句
|
||||
int count = stmt.executeUpdate(sql);
|
||||
System.out.println(count);
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// 关闭连接
|
||||
if (stmt != null) {
|
||||
try {
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
| ResultSet | executeQuery(String sql) <br />执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。 |
|
||||
|-----------|-------------------------------------------------------------------|
|
||||
|
||||
通过这个方法可以进行结果集的查询,并且将查询结果包装成ResultSet对象进行返回
|
||||
|
||||
可以使用对应的方法调用
|
||||
|
||||
### 使用指定的列的方式将结果返回
|
||||
|
||||
```java
|
||||
String sql = "select ENAME,SAL from emp";
|
||||
// 发送静态的 select 语句
|
||||
rs = stmt.executeQuery(sql);
|
||||
// re.next() 返回值是一个布尔值,判断是否有下一个
|
||||
while (rs.next()) {
|
||||
// 使用 getString 方法获取对应下标的值,无论是什么类型都会转换为String类型
|
||||
// JDBC 中所有下标从 1 开始
|
||||
String ename = rs.getString(1);
|
||||
// 这里的 1 和 2 代表的一行数据的第几列
|
||||
String sal = rs.getString(2);
|
||||
System.out.println(ename + ", " + sal);
|
||||
```
|
||||
|
||||
### 使用返回列名的方式将结果返回
|
||||
|
||||
> 必须是数据库返回结果的列名,如果重命名则要写重命名后的内容
|
||||
|
||||
```java
|
||||
while (rs.next()) {
|
||||
// 这里也能写取出指定数据的名称,这种方式更加健壮
|
||||
// 以列的名字获取对应的内容
|
||||
// 如果查询结果经过重命名,那么必须写重命名后的内容
|
||||
String ename = rs.getString("ENAME");
|
||||
String sal = rs.getString("SAL");
|
||||
System.out.println(ename + ", " + sal);
|
||||
}
|
||||
```
|
||||
|
||||
### 将指定结果按指定的类型返回
|
||||
|
||||
> 这个类型必须以创建数据库时的指定类型为准
|
||||
|
||||
```java
|
||||
while (rs.next()) {
|
||||
String ename = rs.getString("ENAME");
|
||||
// 直接以数字的形式查询内容【其他方式同理】
|
||||
int sal = rs.getInt("SAL");
|
||||
System.out.println(ename + ", " + (sal+100));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
## PreparedStatement的使用
|
||||
|
||||
- 可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
|
||||
|
||||
- PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
|
||||
|
||||
- PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,
|
||||
|
||||
调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,
|
||||
|
||||
第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),
|
||||
|
||||
第二个是设置的 SQL 语句中的参数的值
|
||||
|
||||
## PreparedStatement和Statement的区别
|
||||
|
||||
PreparedStatement 解决了SQL注入问题
|
||||
|
||||
Statement 是预编译一次执行一次,PreparedStatement 是编译一次,可执行N次。PreparedStatement 效率更高。
|
||||
|
||||
PreparedStatement会在编译阶段进行安全检查
|
||||
|
||||
如果业务中需要使用SQL注入的时候会使用 Statement,使用场景:在列表升序和降序的排序中,需要将内容拼入行尾
|
||||
@@ -0,0 +1,70 @@
|
||||
## JDBC中的事务
|
||||
|
||||
JDBC中的默认事务是自动提交
|
||||
|
||||
将JDBC中的事务设置为手动提交
|
||||
|
||||
然后进行数据库的修改,如果没有出现异常并且数据正常,进行提交
|
||||
|
||||
如果出现异常,直接回滚数据
|
||||
|
||||
```java
|
||||
Connection conn = null;
|
||||
PreparedStatement pr = null;
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test", "root", "123456");
|
||||
// 将自动提交禁用
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "update t_user set realName = ? where id = ? ";
|
||||
pr = conn.prepareStatement(sql);
|
||||
pr.setString(1,"123");
|
||||
pr.setInt(2,15);
|
||||
int count = pr.executeUpdate();
|
||||
|
||||
pr.setString(1,"123");
|
||||
pr.setInt(2,16);
|
||||
count += pr.executeUpdate();
|
||||
|
||||
// 如果能到这里一定没有问题,将数据进行提交
|
||||
conn.commit();
|
||||
System.out.println(count);
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
// 如果出现异常,直接将数据库进行回滚
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.rollback();
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (pr != null) {
|
||||
}
|
||||
if (conn != null) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 乐观锁和悲观锁
|
||||
|
||||
乐观锁:支持并发,事务不需要排队,之不要需要一个版本号
|
||||
|
||||
多线程之间同时进行数据的修改:
|
||||
|
||||
第一个线程先修改数据,并将版本号从1.0更新到1.1
|
||||
|
||||
第二个线程更新完数据后,发现版本号是1.1和最初的版本号不同,会自动回滚
|
||||
|
||||
如果多个线程更新数据,更新前版本号和更新后的版本号一致,那么数据安全,会提交
|
||||
|
||||
悲观锁(行级锁):事务必须排队,数据被锁住了,不允许并发
|
||||
|
||||
在查询语句后加上 for updata 就是行级锁
|
||||
|
||||
```sql
|
||||
select username
|
||||
from t_user
|
||||
where username like '%a_' for update
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
# JDBC
|
||||
|
||||
|
||||
### 简介
|
||||
|
||||
|
||||
### 目录
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
TODO
|
||||
@@ -1,11 +0,0 @@
|
||||
# 计算机基础知识
|
||||
### 简介
|
||||
|
||||
计算机基础相关知识...
|
||||
|
||||
### 目录
|
||||
+ [操作系统基础](./01 操作系统基础)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user