A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

[学习交流] 【成都校区】JDBC

© 哈哈大圣 中级黑马   /  2018-12-6 15:17  /  402 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 哈哈大圣 于 2018-12-6 15:19 编辑

# JDBC

## 一、JDBC介绍【Java DataBase Connectivity】

**JDBC规范定义接口,具体的实现由各大数据库厂商来实现。**

> JDBC是Java访问关系型数据库的标准规范接口,真正怎么操作数据库还需要具体的实现类,也就是**数据库驱动**,**数据库驱动由数据库厂商提供对应的jar包**。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要使用**多态**方式调用 JDBC 接口中的方法即可。

### 1. 使用JDBC的好处
1. 调用JDBC接口中的方法,即可开发访问数据库的程序。
2. 使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库

@@@@@@@@@@@@@@@@@@@@@@@@@ JDBC

### 2. 使用JDBC开发使用到的包

|包|说明|
---|---|
java.sql|所有与JDBC访问数据库相关的接口和类|
javax.sql|数据库扩展包,提供数据库额外的功能。如:连接池|
数据库的驱动|由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类|

### 3. JDBC的核心API

> 通过数据库厂商提供的DriverManager类,使用接口以**多态**的形式调用对应的实现类!

|接口或类|作用|
---|---|
DriverManager类|管理和注册数据库驱动;得到数据库连接对象|
Connection接口|一个连接对象,可用于创建Statement和PreparedStatement对象|
Statement接口|一个SOL语句对象,用于将SQL语句发送给数据库服务器|
PreparedStatement接口|一个SQL语句对象,是Statement的子接口|
ResultSet接口|用于封装数据库查询的结果集,返回给客户端Java程序|

- 使用时需要相关jar导入包添加成库!
> 右键工程--new Directory 文件夹 lib--复制jar包到此路径下--右击该包--Add as Library...

### 4. 加载和注册驱动

> 加载注册驱动就是手动通过**类加载器**将驱动类com.mysql.jdbc.Driver.class文件【内部会加载其他相关联的.class文件<DriverManager.registerDriver(new Driver())注册数据库驱动>】加载到JVM的方法区,以便使用!

|加载和注册驱动的方法|描述|
---|---|
Class.forName(数据库驱动实现类)|加载和注册数据库驱动,数据库驱动有mysql厂商提供,"com.mysql.jdbc.Driver"


```
Class.forName("com.mysql.jdbc.Driver");
```

> 从 JDBC3 开始,目前已经普遍使用的版本。可以不用注册驱动而直接使用。Class.forName这句话可以省略。

## 二、DriverManager类

- DriverManager作用:
    1. 管理和注册驱动
    2. 创建数据库的连接

### 1.类中的方法

- **`Connection getConnection(String url,String user,String password)`**:通过连接字符串,用户名,密码来得到数据库的连接对象。
- **`Connection gerConnection(String url,Properties info)`**:通过连接字符串,属性对象来得到连接对象。

### 2.使用JDBC连接数据库的四个参数
1. **用户名**:登录的用户名
2. **密码**:登录的密码
3. **连接字符串URL**:不同的数据库URL是不同的,mysql的写法 **`jdbc:mysql://localhost:3306/数据库[?参数名=参数值]`**
4. 连接数据库的URL地址格式: **`协议名:子协议://服务器名或者IP地址:端口号/数据库名?参数=参数值`**

- **MySQL写法**
    > jdbc:mysql://localhost:3306/test?参数=参数值
    > --|--------|----------|----------|-------|
    > 协议-子协议     主机IP:  端口  数据库

- **简写形式**【必须是本地服务器,端口号是3306】
    > **`jdbc:mysql:///数据库名`**

- **乱码的处理**
> 如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。
```
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
```

### 3.案例演示

- **使用用户名、密码、RUL得到连接对象**

```java
String url = "jdbc:mysql://localhost:3306/jdbclearn";
Connection connection = DriverManager.getConnection(url,"root","abc123");
System.out.println(connection);
connection.close();
```


- **使用属性文件和url得到连接对象**
```java
String url = "jdbc:mysql://localhost:3306/jdbclearn";
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
Connection connection = DriverManager.getConnection(url,info);
System.out.println(connection);
connection.close();
```

## 三、Connection接口

> **Connection接口作用:** 具体的实现由数据库的厂商实现,代表一个连接对象。

### 1.Connection接口中的方法
- **`Statement createStatement()`**: 创建一条SQL语句对象


## 四、Statement接口

### 1.JDBC访问数据库的步骤

@@@@@@@@@@@@@@@@@@@@@@ JDBC访问数据库的步骤

1. 注册和加载驱动(可以省略)。
2. 获取连接对象**Connection**【登录】。
3. 通过Connection获取**Statement**对象【获得SQL执行代理对象】。
4. 返回结果集。
5. 释放资源。

### 2.Statement接口中的方法:
- **`int executeUpdate(String sql)`**:
    - 用于发送DML语句,增删改的操作,**`insert`,`update`,`delete`**
    - 参数:SQL语句
    - 返回值:返回对数据库影响的行数
- **`ResultSet executeQuery(String sql)`**:
    - 用于发送DQL语句,执行查询的操作。**`select`**
    - 参数:SQL语句
    - 返回值:查询的结果集
- `boolean execute(String sql)`: 可执行任意sql,基本不用!

### 3.释放资源

- 需要释放的对象:
    - **ResultSet结果集**、
    - **Statement语句**、
    - **Connection连接**
- 释放原则:
    - 先开的后关,后开的先关!
    - **ResultSet** -> **Statement** -> **Connection**
- 放置的位置:**`finally`**代码块

## 五、执行DDL操作

- 使用 JDBC 在 MySQL 的数据库中创建一张学生表
```
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
* 创建一张学生表
*/
public class CreateTableStudent {
    public static void main(String[] args) {
        // 创建连接
        Connection conn = null;
        Statement statement = null;
        try {
            // 获得连接对象
            conn = DriverManager.getConnection("jdbc:mysql:///jdbclearn", "root", "abc123");

            // 获得语句代理对象
            statement = conn.createStatement();

            // 发送SQL语句给服务器
            Integer res = statement.executeUpdate(
                    "create table student (" +
                            "id int primary key auto_increment," +
                            "name varchar(20) not null," +
                            "gender boolean," +
                            "birthday date)"
            );
            // DDL没有返回值!
            System.out.println("创建成功res:" + res);
        } catch (SQLException e){ e.printStackTrace();
        } finally {
            // 释放资源
            if(statement != null){ try { statement.cancel(); } catch (SQLException e){ e.printStackTrace(); } }
            if(conn != null) { try { conn.close(); } catch (SQLException e){ e.printStackTrace(); } }
        }
    }

}
```

## 六、执行DML操作

- 向学生表中添加 4 条记录,主键是自动增长

```
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class InsertSomeData {

    public static void main(String[] args) {
        // 创建连接对象
        Connection connection  = null;
        Statement statement = null;

        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbclearn","root", "abc123");
            statement = connection.createStatement();
            Integer res = statement.executeUpdate(
                    "insert into student value" +
                            "(null,'孙悟空',1,'1993-03-24')," +
                            "(null,'白骨精',0,'1995-03-24')," +
                            "(null,'猪八戒',1,'1903-03-24')," +
                            "(null,'嫦娥',0,'1993-03-11');"
            );
            System.out.println("数据插入成功,供插入了" + res + "条数据。");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if(statement != null){ try { statement.close(); } catch (SQLException e){ e.printStackTrace(); }}
            if(connection != null){ try { connection.close(); } catch (SQLException e){ e.printStackTrace(); } }
        }
    }
}
```


## 七、执行DQL操作

### ResultSet接口

> **作用**: 封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。

----
@@@@@@@@@@@@@@@@@@@@@@ JDBCResultSet接口.png

### 1.接口中的方法
- **`boolean next()`**:
    - 游标向下移动一行。
    - 返回boolean类型,如果还有下一条记录,返回true,否则返回false。
- **`数据类型 getXxx()`**: 每个类型都重载方法,方法签名有两种,如下
    1. 通过字段名,参数是String类型,返回不同的类型。
    2. 通过列号,参数是整数,从1开始。返回不同的类型。

### 2.以字段名签名为例,介绍这些方法:
1. **`boolean getBoolean(String col)`**:以Java中boolean形式获取此ResultSet对象的当前行中指定列的值。
2. **`byte getByte(String col)`**:以Java中byte形式...
3. **`short getShort(String col`**:以Java中short形式...
4. **`long getLong(String col)`**:以Java中long形式...
5. **`float getFloat(String col)`**:以Java中float形式...
6. **`double getDouble(String col)`**:以Java中double形式...
7. **`String getString(col)`**:以Java中String形式...

### 3.常用数据类型转换表

|SQL 类型| Jdbc 对应方法 |返回类型
---|---|---|
BIT(1) bit(n) |getBoolean() |boolean|
TINYINT |getByte() |byte|
SMALLINT |getShort() |short|
INT |getInt() |int|
BIGINT |getLong()| long|
CHAR,VARCHAR| getString() |String|
Text(Clob) Blob |getClob getBlob() |Clob Blob|
DATE |getDate() |java.sql.Date 只代表日期|
TIME |getTime() |java.sql.Time 只表示时间|
TIMESTAMP |getTimestamp()| java.sql.Timestamp 同时有日期和时间|

> **`java.sql.Date`、`Time`、`Timestamp(时间戳)`,三个共同父类是:`java.util.Date`**

### 4.ResultSet接口中的注意事项
1) 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set
2) 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set
3) 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection

### 5.小试牛刀

- 查询student表中所有学员的信息

```
import java.sql.*;
public class GetMsgFromStudent {

    public static void main(String[] args) {
        // 创建连接、执行、结果集 对象
        Connection connection = null;
        Statement statement = null;
        ResultSet rs = null;
        try {
            // 获得连接对象
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbclearn","root", "abc123");
            statement = connection.createStatement();
            rs = statement.executeQuery("select * from student;");

            // 遍历结果集,读取每一条记录信息。
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                boolean gender = rs.getBoolean("gender");
                Date birthday = rs.getDate("birthday");
                System.out.println("编号:" + id + " 姓名:" + name
                + " 性别:" + (gender?"男":"女") + " 生日:" + birthday);
            }

        } catch (SQLException e) { e.printStackTrace();
        } finally {
            if(rs != null){ try { rs.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(); } }
        }
    }
}
```

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马