概述

JDBC(java database connectivity)是java访问数据库的操作规范,实质上就是一个接口,具体的实现类(数据库驱动)由各个具体的数据库厂商实现。

JDBC核心API

接口或者类 作用
DriverManager类 管理和注册数据库驱动(DriverManager.registerDriver)、获取数据库连接对象(DriverManager.getConnection)
Connection接口 连接对象,可以创建Statement和PreparedStatement对象(con.createStatement)
Statement接口 SQL语句对象,将SQL语句发送给数据库服务器
PreparedStatement接口 SQL语句对象,是Statement子接口,预编译对象,可以防止SQL注入
ResultSet接口 用于封装数据库查询的结果集,返回给客户端的java服务器。用next方法是游标。用getXxx方法获取该行不同字段结果

快速入门

导入驱动Jar包

新建文件夹lib,然后将Jar包放在该文件夹下,右键选择添加成library(Add as Library)

加载和注册驱动

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

为何可以这样注册驱动?我们知道将com.mysql.jdbc.Driver加载进内存,会自动执行给类中静态代码块。

在该类的静态代码块中有注册驱动的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
//Driver接口,所有数据库厂商必须实现的接口,表示这是一个驱动类
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
//该类加载进内存,会执行静态代码块
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

注意:从JDBC3开始,目前已经普遍使用的版本,可以不用注册驱动直接使用。因为导入的驱动Jar包中META-INF文件中有对应的注册驱动配置

详解JDBC重要的API

DriverManager类

驱动管理,用于注册驱动(Class将驱动类加载,自动执行注册驱动)或者获取连接对象

获取连接对象

1
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root");

连接数据库的 URL 地址格式

协议名:子协议://服务器或者IP地址:端口号/数据库名?参数=参数值

举例

1
jdbc:mysql://localhost:3306/db3?msg=hello

如果默认本机3306端口可以省略localhost:3306

1
jdbc:mysql:///db3

乱码处理

如果数据库出现乱码,可以指定参数?characterEncoding=utf8

1
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8

案例1使用用户名、密码、URL 得到连接对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* 得到连接对象
*/
public class Demo2 {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/day24";
//1) 使用用户名、密码、URL 得到连接对象
Connection connection = DriverManager.getConnection(url, "root", "root");
//com.mysql.jdbc.JDBC4Connection@68de145
System.out.println(connection);
} }

案例2使用属性文件和 url 得到连接对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class Demo3 {
public static void main(String[] args) throws SQLException {
//url 连接字符串
String url = "jdbc:mysql://localhost:3306/day24";
//属性对象
Properties info = new Properties();
//把用户名和密码放在 info 对象中
info.setProperty("user","root");
info.setProperty("password","root");
Connection connection = DriverManager.getConnection(url, info);
//com.mysql.jdbc.JDBC4Connection@68de145
System.out.println(connection);
} }

Connection接口

Connection 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。

接口中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

### Statement接口

代表语句对象,用于**发送SQL语句给服务器**,用于执行静态SQL语句并返回它生成结果的对象。

#### 接口中的方法

executeUpdate 更新

executeQuery 查询

### PreparedStatement接口

代表语句对象,用于**发送SQL语句给服务器**,这里的SQL语句参数要用?代替。用于执行**动态**SQL语句并返回它生成结果的对象。

#### 可以防止SQL注入

本质上是和服务器协调固定了SQL语句的结构,防止了SQL注入。

#### 接口中的方法

setXxx 设置?对应的参数

### ResultSet接口

结果集对象,封装了查询结果

#### 接口中的方法

##### boolean next()

游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true

##### getXxx(参数) 获取数据

Xxx:代表数据类型 如: int getInt() , String getString()
参数

1. int:代表列的编号,从1开始 如: getString(1)
2. String:代表列名称。 如: getDouble("balance")

## JDBC连接数据库步骤

- 导入数据库驱动jar包
- 加载注册驱动
- 获取连接对象
- 创建语句对象statement
- 定义sql,利用statement对象给数据库服务器发送执行
- 返回执行结果
- 关闭statement、connecttion、(resultSet)

## 抽取JDBC工具类 : JDBCUtils

主要是为了简化书写

### 步骤

- 定义jdbc.properties配置文件,包括```url、user、password、driver```属性
- 定义类,定义静态方法
- 定义property对象,读取配置文件属性
- 加载注册jdbc(静态代码块)
- 定义获取连接对象静态方法
- 定义close方法

### 代码

```java
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
*/
static{
//读取资源文件,获取值。

try {
//1. 创建Properties集合类。
Properties pro = new Properties();

//获取src路径下的文件的方式--->ClassLoader 类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
//2. 加载文件
// pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties"));
pro.load(new FileReader(path));

//3. 获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4. 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {

return DriverManager.getConnection(url, user, password);
}

/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

JDBCUtils使用

直接使用静态类JDBCUtils静态方法创建连接对象。最后使用该类的close关闭statement、connection、resultset对象

如果需要修改JDBCUtils配置在jdbc.properties进行修改。

案例通过查询user表,实现查询登录功能

步骤分析

  1. 使用JDBCUtils对象连接数据库
  2. 查询user数据库表,如果查询有结果,则表示成功登录

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    /**
* 登录方法
*/
public boolean login(String username ,String password){
if(username == null || password == null){
return false;
}
//连接数据库判断是否登录成功
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = '"+username+"' and password = '"+password+"' ";
//3.获取执行sql的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
/* if(rs.next()){//如果有下一行,则返回true
return true;
}else{
return false;
}*/
return rs.next();//如果有下一行,则返回true

} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(rs,stmt,conn);
}
return false;
}
}

JDBC控制事务

事务概述

一个包含多个步骤的业务,我们期望他要么全部执行成功,要么同时执行失败。

操作

  • 开启事务 setAutoCommit(false)
  • 成功,手动commit,提交事务
  • 失败(捕获到异常),手动rollback,回滚事务

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class JDBCDemo10 {

public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;

try {
//1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);

//2.定义sql
//2.1 张三 - 500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2 李四 + 500
String sql2 = "update account set balance = balance + ? where id = ?";
//3.获取执行sql对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4. 设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);

pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5.执行sql
pstmt1.executeUpdate();
// 手动制造异常
int i = 3/0;

pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
//事务回滚
try {
if(conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
}

参考

1.黑马JDBC笔记

概述

数据库连接池是一个存放connection连接对象的池子(容器)。

作用

当系统初始化后,容器被创建,容器会申请一些连接对象存放在该容器中,当用户访问数据库的时候,直接从池子中申请,用完后归还到池子中去。

好处

  • 节约资源
  • 用户访问高效

实现

接口

标准的接口是DataSource,包含方法

  • 获取连接getConnection
  • 归还连接close

具体实现

一般是由数据库厂商来实现

  • C3P0数据库连接池技术
  • Druid(阿里巴巴提供)

快速使用

C3P0数据库连接池技术

步骤

  1. 导入jar包(注意要导入数据库连接池的jar包,还要导入数据库驱动jar包)
  2. 在src(classPath)下定义配置文件,可以配置driverName,user,password,maxSize等
  3. 定义一个类文件使用
    • ds=new ComboPooledDataSource直接new一个连接池
    • 数据库连接池直接getConnection获取连接对象

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package cn.itcast.dataSource.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class Demo1 {
public static void main(String[] args) {

try {
DataSource ds=new ComboPooledDataSource("other1c3p0");
Connection con = ds.getConnection();
System.out.println(con);
con.close();
} catch (SQLException e) {
e.printStackTrace();
}

}
}

Druid(阿里巴巴提供)常用

步骤

  1. 导入jar包(注意要导入数据库连接池的jar包,还要导入数据库驱动jar包)
  2. 在src(classPath)下定义配置文件,可以配置driverName,user,password,maxSize等
  3. 定义一个类文件使用
    • ds=DruidDataSourceFactory.createDataSource(pro)这里是通过工厂类来生成连接池
    • 数据库连接池直接getConnection获取连接对象

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package cn.itcast.dataSource.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class Demo01 {
public static void main(String[] args) {
Properties pro=null;
try {
pro = new Properties();
InputStream rs = Demo01.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(rs);
} catch (IOException e) {
e.printStackTrace();
}
try {
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection connection = ds.getConnection();
Statement statement = connection.createStatement();
String sql="SELECT * FROM emp;";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString("ename"));

}
} catch (Exception e) {
e.printStackTrace();
}
}
}

抽取成工具类DruidUtils

功能

  • 获取数据库连接池
  • 获取连接对象
  • 关闭对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cn.itcast.dataSource.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
* druid工具类
* 1.获取连接对象
* 2.关闭连接对象
* 3.获取数据库连接池
*/
public class DruidUtils {
private static DataSource ds;

static {
try {
Properties pro = new Properties();
InputStream rs = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(rs);
ds = DruidDataSourceFactory.createDataSource(pro);//初始化数据池对象

} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 获取连接对象
*
* @return
*/
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

/**
* 获取数据池
*
* @return
*/
public static DataSource getDataSource() {
return ds;
}

/**
* 关闭对象
*
* @param rs
* @param stmt
* @param con
*/
public static void close(ResultSet rs, Statement stmt, Connection con) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public static void close(Statement stmt, Connection con) {
DruidUtils.close(null, stmt, con);
}


}


Spring JDBC(JDBCTemplate)常用

概述

Spring框架对JDBC的简单封装。提供了JDBCTemplate对象简化JDBC的开发。JDBCTemplate对象能自动close对象,极大方便了操作。

步骤

  1. 导入jar包

  2. 创建JDBCTemplate对象。参数为数据库连接池DataSource

    1
    2
    DataSource ds= DruidUtils.getDataSource();
    JdbcTemplate tmp=new JdbcTemplate(ds);
  3. 调用方法来实现

    • update
    • query(查询,通过BeanPropertyRowMapper封装成对象列表)
    • queryForObeject(查询,通过BeanPropertyRowMapper封装成对象)
    • queryForMap
    • queryForList

代码举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package cn.itcast.dataSource.jdbctmplate;

import cn.itcast.dataSource.domain.Emp;
import cn.itcast.dataSource.utils.DruidUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.List;

public class JDBCTemplateDemo01 {
public static void main(String[] args) {
DataSource ds= DruidUtils.getDataSource();
JdbcTemplate tmp=new JdbcTemplate(ds);
String sql="SELECT * FROM emp where id=1001";
//封装成对象,参数用BeanPropertyRowMapper接口
Emp emp = tmp.queryForObject(sql, new BeanPropertyRowMapper<>(Emp.class));
System.out.println(emp);


String sql1="SELECT * FROM emp;";
//封装成对象列表,参数用BeanPropertyRowMapper接口
List<Emp> emps = tmp.query(sql1, new BeanPropertyRowMapper<>(Emp.class));
for (Emp emp1 : emps) {
System.out.println(emp1);
}

//查询总的数据条数
String sql2="SELECT count(id) FROM emp;";
Long num = tmp.queryForObject(sql2, Long.class);
System.out.println(num);


}
}