核心概述:在实际开发中,我们需要通过Java程序来操作数据库,此时Java给我们提供了Java访问数据库的标准规范就是JDBC,我们可以通过调用JDBC接口中的方法实现操作数据库。

  • 第一章:JDBC快速入门

    • 1.1-客户端操作MySQL的方式

    • 1.2-JDBC概述

    • 1.3-JDBC核心API

    • 1.4-导入驱动jar包

    • 1.5-加载和注册驱动

  • 第二章:DriverManager类

    • 2.1-DriverManager作用

    • 2.2-类中的方法

    • 2.3-连接数据库的四个参数

    • 2.4-连接数据库URL

    • 2.5-代码演示

  • 第三章:Connection接口

  • 第四章:Statement 接口

    • 4.1-JDBC访问数据库的步骤

    • 4.2-Statement 作用

    • 4.3-Statement 中的方法

    • 4.4-释放资源

    • 4.5-执行DDL

    • 4.6-执行DML

    • 4.7-执行DQL

  • 第五章:数据库工具类 JdbcUtils

  • 第六章:用户登录案例

    • 6.1-需求

    • 6.2-步骤

    • 6.3-SQL 注入问题

  • 第七章:PreparedStatement 接口

    • 7.1-继承结构与作用

    • 7.2-PreparedSatement 的执行原理

    • 7.3-PreparedStatement 对象

    • 7.4-使用 PreparedStatement 的步骤

    • 7.5-表与类的关系

    • 7.6-PreparedStatement 执行 DML 操作

  • 第八章:JDBC处理事务

    • 8.1-准备数据

    • 8.2-API介绍

    • 8.3-开发步骤

  • 第九章:数据库连接池

    • 9.1-为什么要学习数据库连接池

    • 9.2-什么是数据库连接池

    • 9.3-如何使用数据库连接池

    • 9.4-C3P0

    • 9.5-Druid

    • 9.6-DruidUtils

  • 第十章:Spring JDBC

    • 10.1-概述

    • 10.2-使用Spring JDBC

第一章:JDBC快速入门

1.1-客户端操作MySQL的方式

01-使用第三方客户端来访问 MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL 。

02-使用 MySQL 自带的命令行方式 。

03-通过 Java 来访问 MySQL 数据库,本篇要讲解的内容

1.2-JDBC概述

什么是JDBC

JDBC (Java Database Connectivity,简称JDBC )是 Java 访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个 数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用 JDBC 接口中的方法即可,数据库驱动由数据库厂商提供。

JDBC的好处

01-程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。

02-使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库 。

使用 JDBC 开发使用到的包

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

1.3-JDBC核心API

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

1.4-导入驱动jar包

下载

链接:https://pan.baidu.com/s/1igjB1mTP7GBLBAZGP_bsGA
提取码:v72g

导入步骤

1.5-加载和注册驱动

加载方法

加载和注册驱动的方法 描述
Class.forName(数据库驱动实现类) 加载和注册数据库驱动,数据库驱动由 mysql 厂商”com.mysql.jdbc.Driver”

具体实现

public class Demo1 {

public static void main(String[] args) throws ClassNotFoundException {

//抛出类找不到的异常,注册数据库驱动

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

}

}

疑问:为什么这样可以注册驱动?

public class Driver implements java.sql.Driver {

public Driver() throws SQLException {

}

static {

try {

DriverManager.registerDriver(new Driver()); //注册数据库驱动

} catch (SQLException var1) {

throw new RuntimeException("Can't register driver!");

}

}

}

com.mysql.jdbc.Driver 源代码:

Driver 接口,所有数据库厂商必须实现的接口,表示这是一个驱动类。

注意事项

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

为了向下兼容,建议不要省略。

第二章:DriverManager类

2.1-DriverManager作用

  1. 管理和注册驱动

  2. 创建数据库的连接

2.2-类中的方法

DriverManager 类中的静态方法 描述
Connection getConnection (String url, String user, String password) 通过连接字符串,用户名,密码来得到数据库的连接对象
Connection getConnection (String url, Properties info) 通过连接字符串,属性对象来得到连接对象

2.3-连接数据库的四个参数

参数 说明
用户名 登录的用户名
密码 登录的密码
连接字符串 URL 不同的数据库 URL 是不同的
mysql 的写法jdbc:mysql://localhost:3306/数据库[?参数名=参数值]
驱动类的字符串名 com.mysql.jdbc.Driver

2.4-连接数据库URL

格式

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

MySQL格式

MySQL简写格式

前提:必须是本地服务器,端口号是 3306 。

简写格式:jdbc:mysql:///数据库名

乱码的处理

如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。

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

2.5-代码演示

方式1:使用用户名、密码、URL 得到连接对象

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/db3";

//1) 使用用户名、密码、URL 得到连接对象

Connection connection = DriverManager.getConnection(url, "root", "root");

//com.mysql.jdbc.JDBC4Connection@68de145

System.out.println(connection);

}

}

方式2:使用属性文件和 url 得到连接对象

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/db3";

//属性对象

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 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。

方法

方法 描述
Statement createStatement() 创建一条 SQL 语句对象

第四章:Statement 接口

4.1-JDBC访问数据库的步骤

  1. 注册和加载驱动(可以省略)

  2. 获取连接

  3. Connection Statement 对象

  4. 使用 Statement 对象执行 SQL 语句

  5. 返回结果集

  6. 释放资源

4.2-Statement 作用

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

4.3-Statement 中的方法

Statement 接口中的方法 描述
int executeUpdate(String sql) 用于发送 DML 语句,增删改的操作(insert、update、delete) 参数:SQL 语句 返回值:返回对数据库影响的行数
ResultSet executeQuery(String sql) 用于发送 DQL 语句,执行查询的操作。select 参数:SQL 语句 返回值:查询的结果集

4.4-释放资源

  1. 需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接

  2. 释放原则:先开的后关,后开的先关。ResultSet →Statement →Connection

  3. 放在哪个代码块中:finally 块

4.5-执行DDL

需求:使用 JDBC 在 MySQL 的数据库中创建一张学生表

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

/**

* 创建一张学生表

*/

public class Demo4DDL {

public static void main(String[] args) {

//1. 创建连接

Connection conn = null;

Statement statement = null;

try {

conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");

//2. 通过连接对象得到语句对象

statement = conn.createStatement();

//3. 通过语句对象发送 SQL 语句给服务器

//4. 执行 SQL

statement.executeUpdate("create table student (id int PRIMARY key auto_increment, " +

"name varchar(20) not null, gender boolean, birthday date)");

//5. 返回影响行数(DDL 没有返回值)

System.out.println("创建表成功");

} catch (SQLException e) {

e.printStackTrace();

}

//6. 释放资源

finally {

//关闭之前要先判断

if (statement != null) {

try {

statement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (conn != null) {

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

}

4.6-执行DML

需求

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

步骤

  1. 创建连接对象

  2. 创建 Statement 语句对象

  3. 执行 SQL 语句:executeUpdate(sql)

  4. 返回影响的行数

  5. 释放资源

代码

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

/**

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

*/

public class Demo5DML {

public static void main(String[] args) throws SQLException {

// 1) 创建连接对象

Connection connection = DriverManager.getConnection("jdbc:mysql:///day24", "root",

"root");

// 2) 创建 Statement 语句对象

Statement statement = connection.createStatement();

// 3) 执行 SQL 语句:executeUpdate(sql)

int count = 0;

// 4) 返回影响的行数

count += statement.executeUpdate("insert into student values(null, '孙悟空', 1, '1993-03-

24')");

count += statement.executeUpdate("insert into student values(null, '白骨精', 0, '1995-03-

24')");

count += statement.executeUpdate("insert into student values(null, '猪八戒', 1, '1903-03-

24')");

count += statement.executeUpdate("insert into student values(null, '嫦娥', 0, '1993-03-

11')");

System.out.println("插入了" + count + "条记录");

// 5) 释放资源

statement.close();

connection.close();

}

}

4.7-执行DQL

ResultSet 接口

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

接口中的方法:

其他方法

常用的数据类型转换表

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

需求

确保数据库中有 3 条以上的记录,查询所有的学员信息

步骤

  1. 得到连接对象

  2. 得到语句对象

  3. 执行 SQL 语句得到结果集 ResultSet 对象

  4. 循环遍历取出每一条记录

  5. 输出的控制台上

  6. 释放资源

代码

import java.sql.*;

/**

* 查询所有的学生信息

*/

public class Demo6DQL {

public static void main(String[] args) throws SQLException {

//1) 得到连接对象

Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/day24","root","root");

//2) 得到语句对象

Statement statement = connection.createStatement();

//3) 执行 SQL 语句得到结果集 ResultSet 对象

ResultSet rs = statement.executeQuery("select * from student");

//4) 循环遍历取出每一条记录

while(rs.next()) {

int id = rs.getInt("id");

String name = rs.getString("name");

boolean gender = rs.getBoolean("gender");

Date birthday = rs.getDate("birthday");

//5) 输出的控制台上

System.out.println("编号:" + id + ", 姓名:" + name + ", 性别:" + gender + ", 生日:" +

birthday);

}

//6) 释放资源

rs.close();

statement.close();

connection.close();

}

}

结果

ResultSet使用注意事项

  1. 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set

  2. 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set

  3. 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection

第五章:数据库工具类 JdbcUtils

如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。

需求

上面写的代码中出现了很多重复的代码,可以把这些公共代码抽取出来

代码实现

  1. 可以把几个字符串定义成常量:用户名,密码,URL,驱动类

  2. 得到数据库的连接:getConnection()

  3. 关闭所有打开的资源: close(Connection conn, Statement stmt)close(Connection conn, Statement stmt, ResultSet rs)

import java.sql.*;

/**

* 访问数据库的工具类

*/

public class JdbcUtils {

//可以把几个字符串定义成常量:用户名,密码,URL,驱动类

private static final String USER = "root";

private static final String PWD = "root";

private static final String URL = "jdbc:mysql://localhost:3306/day24";

private static final String DRIVER= "com.mysql.jdbc.Driver";

/**

* 注册驱动

*/

static {

try {

Class.forName(DRIVER);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

/**

* 得到数据库的连接

*/

public static Connection getConnection() throws SQLException {

return DriverManager.getConnection(URL,USER,PWD);

}

/**

* 关闭所有打开的资源

*/

public static void close(Connection conn, Statement stmt) {

if (stmt!=null) {

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (conn!=null) {

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

/**

* 关闭所有打开的资源

*/

public static void close(Connection conn, Statement stmt, ResultSet rs) {

if (rs!=null) {

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

close(conn, stmt);

}

}

第六章:用户登录案例

6.1-需求

  1. 有一张用户表

  2. 添加几条用户记录

  3. 使用 Statement 字符串拼接的方式实现用户的登录, 用户在控制台上输入用户名和密码。

create table user (

id int primary key auto_increment,

name varchar(20),

password varchar(20)

)

insert into user values (null,'jack','123'),(null,'rose','456');

-- 登录, SQL 中大小写不敏感

select * from user where name='JACK' and password='123';

-- 登录失败

select * from user where name='JACK' and password='333';

6.2-步骤

  1. 得到用户从控制台上输入的用户名和密码来查询数据库

  2. 写一个登录的方法

  • 通过工具类得到连接

  • 创建语句对象,使用拼接字符串的方式生成 SQL 语句

  • 查询数据库,如果有记录则表示登录成功,否则登录失败

  • 释放资源

import com.it.utils.JdbcUtils;

import javax.xml.transform.Result;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Scanner;

public class Demo7Login {

//从控制台上输入的用户名和密码

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

System.out.println("请输入用户名:");

String name = sc.nextLine();

System.out.println("请输入密码:");

String password = sc.nextLine();

login(name, password);

}

/**

* 登录的方法

*/

public static void login(String name, String password) {

//a) 通过工具类得到连接

Connection connection = null;

Statement statement = null;

ResultSet rs = null;

try {

connection = JdbcUtils.getConnection();

//b) 创建语句对象,使用拼接字符串的方式生成 SQL 语句

statement = connection.createStatement();

//c) 查询数据库,如果有记录则表示登录成功,否则登录失败

String sql = "select * from user where name='" + name + "' and password='" + password

+ "'";

System.out.println(sql);

rs = statement.executeQuery(sql);

if (rs.next()) {

System.out.println("登录成功,欢迎您:" + name);

} else {

System.out.println("登录失败");

}

} catch (SQLException e) {

e.printStackTrace();

} finally {

//d) 释放资源

JdbcUtils.close(connection, statement, rs);

}

}

}

6.3-SQL 注入问题

现象

当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了

请输入用户名:

newboy

请输入密码:

a' or '1'='1

select * from user where name='newboy' and password='a' or '1'='1'

登录成功,欢迎您:newboy

问题分析

select * from user where name='newboy' and password='a' or '1'='1'

-- name='newboy' and password='a' 为假

-- '1'='1' 真

-- 相当于

select * from user where true; -- 查询了所有记录

我们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容作为了 SQL 语句语法的一部分,改变了 原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进 行简单的字符串拼接。

第七章:PreparedStatement 接口

7.1-继承结构与作用

PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句

7.2-PreparedSatement 的执行原理

  1. 因为有预先编译的功能,提高 SQL 的执行效率。

  2. 可以有效的防止 SQL 注入的问题,安全性更高。

7.3-PreparedStatement 对象

创建

常用方法

作用

  1. prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。

  2. 安全性更高,没有 SQL 注入的隐患。

  3. 提高了程序的可读性

7.4-使用 PreparedStatement 的步骤

  1. 编写 SQL 语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?";

  2. 获得 PreparedStatement 对象

  3. 设置实际参数:setXxx(占位符的位置, 真实的值)

  4. 执行参数化 SQL 语句

  5. 关闭资源

使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况

import com.it.utils.JdbcUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.Scanner;

/**

* 使用 PreparedStatement

*/

public class Demo8Login {

//从控制台上输入的用户名和密码

public static void main(String[] args) throws SQLException {

Scanner sc = new Scanner(System.in);

System.out.println("请输入用户名:");

String name = sc.nextLine();

System.out.println("请输入密码:");

String password = sc.nextLine();

login(name, password);

}

/**

* 登录的方法

* @param name

* @param password

*/

private static void login(String name, String password) throws SQLException {

Connection connection = JdbcUtils.getConnection();

//写成登录 SQL 语句,没有单引号

String sql = "select * from user where name=? and password=?";

//得到语句对象

PreparedStatement ps = connection.prepareStatement(sql);

//设置参数

ps.setString(1, name);

ps.setString(2,password);

ResultSet resultSet = ps.executeQuery();

if (resultSet.next()) {

System.out.println("登录成功:" + name);

}

else {

System.out.println("登录失败");

}

//释放资源,子接口直接给父接口

JdbcUtils.close(connection,ps,resultSet);

}

}

7.5-表与类的关系

案例:使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象

import com.it.entity.Student;

import com.it.utils.JdbcUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

public class Demo9Student {

public static void main(String[] args) throws SQLException {

//创建学生对象

Student student = new Student();

Connection connection = JdbcUtils.getConnection();

PreparedStatement ps = connection.prepareStatement("select * from student where id=?");

//设置参数

ps.setInt(1,2);

ResultSet resultSet = ps.executeQuery();

if (resultSet.next()) {

//封装成一个学生对象

student.setId(resultSet.getInt("id"));

student.setName(resultSet.getString("name"));

student.setGender(resultSet.getBoolean("gender"));

student.setBirthday(resultSet.getDate("birthday"));

}

//释放资源

JdbcUtils.close(connection,ps,resultSet);

//可以数据

System.out.println(student);

}

}

案例:将多条记录封装成集合 List,集合中每个元素是一个 JavaBean 实体类

需求:查询所有的学生类,封装成 List返回

import com.it.entity.Student;

import com.it.utils.JdbcUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

public class Demo10List {

public static void main(String[] args) throws SQLException {

//创建一个集合

List<Student> students = new ArrayList<>();

Connection connection = JdbcUtils.getConnection();

PreparedStatement ps = connection.prepareStatement("select * from student");

//没有参数替换

ResultSet resultSet = ps.executeQuery();

while(resultSet.next()) {

//每次循环是一个学生对象

Student student = new Student();

//封装成一个学生对象

student.setId(resultSet.getInt("id"));

student.setName(resultSet.getString("name"));

student.setGender(resultSet.getBoolean("gender"));

student.setBirthday(resultSet.getDate("birthday"));

//把数据放到集合中

students.add(student);

}

//关闭连接

JdbcUtils.close(connection,ps,resultSet);

//使用数据

for (Student stu: students) {

System.out.println(stu);

}

}

}

7.6-PreparedStatement 执行 DML 操作

import com.it.utils.JdbcUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;

public class Demo11DML {

public static void main(String[] args) throws SQLException {

//insert();

//update();

delete();

}

//插入记录

private static void insert() throws SQLException {

Connection connection = JdbcUtils.getConnection();

PreparedStatement ps = connection.prepareStatement("insert into student

values(null,?,?,?)");

ps.setString(1,"小白龙");

ps.setBoolean(2, true);

ps.setDate(3,java.sql.Date.valueOf("1999-11-11"));

int row = ps.executeUpdate();

System.out.println("插入了" + row + "条记录");

JdbcUtils.close(connection,ps);

}

//更新记录: 换名字和生日

private static void update() throws SQLException {

Connection connection = JdbcUtils.getConnection();

PreparedStatement ps = connection.prepareStatement("update student set name=?, birthday=?

where id=?");

ps.setString(1,"黑熊怪");

ps.setDate(2,java.sql.Date.valueOf("1999-03-23"));

ps.setInt(3,5);

int row = ps.executeUpdate();

System.out.println("更新" + row + "条记录");

JdbcUtils.close(connection,ps);

}

//删除记录: 删除第 5 条记录

private static void delete() throws SQLException {

Connection connection = JdbcUtils.getConnection();

PreparedStatement ps = connection.prepareStatement("delete from student where id=?");

ps.setInt(1,5);

int row = ps.executeUpdate();

System.out.println("删除了" + row + "条记录");

JdbcUtils.close(connection,ps);

}

}

第八章:JDBC处理事务

之前我们是使用 MySQL 的命令来操作事务。接下来我们使用 JDBC 来操作银行转账的事务

8.1-准备数据

CREATE TABLE account (

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(10),

balance DOUBLE

);

-- 添加数据

INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);

8.2-API介绍

8.3-开发步骤

  1. 获取连接

  2. 开启事务

  3. 获取到 PreparedStatement

  4. 使用 PreparedStatement 执行两次更新操作

  5. 正常情况下提交事务

  6. 出现异常回滚事务

  7. 最后关闭资源

import com.it.utils.JdbcUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;

public class Demo12Transaction {

//没有异常,提交事务,出现异常回滚事务

public static void main(String[] args) {

//1) 注册驱动

Connection connection = null;

PreparedStatement ps = null;

try {

//2) 获取连接

connection = JdbcUtils.getConnection();

//3) 开启事务

connection.setAutoCommit(false);

//4) 获取到 PreparedStatement

//从 jack 扣钱

ps = connection.prepareStatement("update account set balance = balance - ? where

name=?");

ps.setInt(1, 500);

ps.setString(2,"Jack");

ps.executeUpdate();

//出现异常

System.out.println(100 / 0);

//给 rose 加钱

ps = connection.prepareStatement("update account set balance = balance + ? where

name=?");

ps.setInt(1, 500);

ps.setString(2,"Rose");

ps.executeUpdate();

//提交事务

connection.commit();

System.out.println("转账成功");

} catch (Exception e) {

e.printStackTrace();

try {

//事务的回滚

connection.rollback();

} catch (SQLException e1) {

e1.printStackTrace();

}

System.out.println("转账失败");

}

finally {

//7) 关闭资源

JdbcUtils.close(connection,ps);

}

}

}

第九章:数据库连接池

9.1-为什么要学习数据库连接池

数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下。
数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池(简单说:在一个“池”里放了好多数据库连接对象),由应用程序动态地对池中的连接进行申请、使用和释放。
对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。
连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

9.2-什么是数据库连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

9.3-如何使用数据库连接池

Java提供了数据库连接池接口:DataSource javax.sql包下的。

数据库厂商实现接口,常用的有以下两种:

  1. C3P0:数据库连接池技术

  2. Druid:数据库连接池实现技术,由阿里巴巴提供的

9.4-C3P0

准备资料

下载

链接:https://pan.baidu.com/s/1XAstwgWObgRM2G1J0iLTLA
提取码:450q

使用步骤

01-导入jar包 (两个) c3p0-0.9.5.2.jar 和 mchange-commons-java-0.2.12.jar 。不要忘记导入数据库驱动jar包

02-定义配置文件。

  • 名称:c3p0.properties 或者 c3p0-config.xml

  • 路径:直接将文件放在src目录下即可。

03-创建核心对象 数据库连接池对象 ComboPooledDataSource。

04-获取数据库连接对象。

c3p0-config.xml配置文件

name="driverClass">com.mysql.jdbc.Driver

name="jdbcUrl">jdbc:mysql://localhost:3306/db2

name="user">root

name="password">root

name="initialPoolSize">5

name="maxPoolSize">10

name="checkoutTimeout">3000

name="otherc3p0">

name="driverClass">com.mysql.jdbc.Driver

name="jdbcUrl">jdbc:mysql://localhost:3306/day25

name="user">root

name="password">root

name="initialPoolSize">5

name="maxPoolSize">8

name="checkoutTimeout">1000

代码演示

public class Test01 {

public static void main(String[] args) throws SQLException {

// 创建数据库连接池对象

DataSource ds = new ComboPooledDataSource();

// 获取数据库连接对象

Connection con = ds.getConnection();

System.out.println(con);

}

}

9.5-Druid

准备资料

下载

链接:https://pan.baidu.com/s/1nWIFTscCI-UODwAEaAy8NQ
提取码:f43e

使用步骤

1. 导入jar包 druid-1.0.9.jar

2. 定义配置文件:

* 是properties形式的

* 可以叫任意名称,可以放在任意目录下

3. 加载配置文件。Properties

4. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory

5. 获取连接:getConnection

druid.properties配置文件

# 数据库驱动

driverClassName=com.mysql.jdbc.Driver

# 数据库连接地址

url=jdbc:mysql://127.0.0.1:3306/db2

# 用户名

username=root

# 密码

password=root

# 初始化连接对象个数

initialSize=5

# 最大个数

maxActive=10

# 超时等待时长

maxWait=3000

代码

public class Test01 {

public static void main(String[] args) throws Exception {

Properties pro = new Properties();

InputStream is = Test01.class.getClassLoader().getResourceAsStream("druid.properties");

pro.load(is);

DataSource ds = DruidDataSourceFactory.createDataSource(pro);

Connection con = ds.getConnection();

System.out.println(con);

}

}

9.6-DruidUtils

DruidUtils

package it.leilei.util;

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;

public class DruidUtils {

private static DataSource ds;

private static InputStream is;

static {

Properties pro = new Properties();

try {

// 读取配置文件

is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");

pro.load(is);

// 创建数据库连接池对象

ds = DruidDataSourceFactory.createDataSource(pro);

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}finally {

if(is!=null){

try {

is.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

// 获取Connection对象

public static Connection getConnection() throws SQLException {

return ds.getConnection();

}

// 释放资源

public static void close(Statement sta, Connection con, ResultSet rs) {

if(sta!=null){

try {

sta.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(con!=null){

try {

con.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(rs!=null){

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

public static void close(Statement sta, Connection con){

close(sta,con,null);

}

// 获取连接池对象

public static DataSource getDataSource(){

return ds;

}

}

测试:向数据库db2中的表account中添加一条新的数据

package it.leilei.DruidDemo;

import it.leilei.util.DruidUtils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;

public class Test02 {

public static void main(String[] args) {

Connection con = null;

PreparedStatement ps = null;

try {

// 获取数据库连接对象

con = DruidUtils.getConnection();

// 定义SQL

String sql = "INSERT INTO account VALUES(NULL,?,?)";

// 创建执行SQL语句对象

ps = con.prepareStatement(sql);

// 给参数设置值

ps.setString(1,"小龙女");

ps.setDouble(2,8000);

// 执行sql

int count = ps.executeUpdate();

if(count>0){

System.out.println("添加成功");

}else {

System.out.println("添加失败");

}

} catch (SQLException e) {

e.printStackTrace();

}finally {

DruidUtils.close(ps,con);

}

}

}

第十章:Spring JDBC

10.1-概述

以上数据库连接池确实优化并简化了Java对SQL的操作,但是在针对增删改查操作时相对还是有些繁琐,在实际开发中,我们通常会使用框架中封装好的JDBC来操作数据库,可以更加简化Java对SQL的操作,提高开发效率。

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。

10.2-使用Spring JDBC

准备资料

下载

链接:https://pan.baidu.com/s/1JLru45Sb3Xog35U_xv7nNA
提取码:73vt

使用步骤

  1. 导入jar包(lib目录下所有jar包)

  • commons-logging-1.2.jar

  • spring-beans-5.0.0.RELEASE.jar

  • spring-core-5.0.0.RELEASE.jar

  • spring-jdbc-5.0.0.RELEASE.jar

  • spring-tx-5.0.0.RELEASE.jar

创建JdbcTemplate对象。依赖于数据源DataSource。

调用JdbcTemplate的方法来完成CRUD的操作

  • 一般用于聚合函数的查询

  • query的参数:RowMapper

  • 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

  • 注意:这个方法查询的结果集长度只能是1

  • update():执行DML语句。增、删、改语句

  • :查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合

  • :查询结果将结果集封装为list集合

  • :查询结果,将结果封装为JavaBean对象

  • queryForObject:查询结果,将结果封装为对象

  1. query()

  2. 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装

  3. new BeanPropertyRowMapper<类型>(类型.class)

  4. queryForList()

  5. queryForMap()

代码演示

package it.leilei.JDBCTemplateDemo;

import it.leilei.domain.Emp;

import it.leilei.util.DruidUtils;

import org.junit.Test;

import org.springframework.dao.DataAccessException;

import org.springframework.jdbc.core.BeanPropertyRowMapper;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.ResultSetExtractor;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.List;

import java.util.Map;

public class Test01 {

// 创建JdbcTemplate对象

private JdbcTemplate jt = new JdbcTemplate(DruidUtils.getDataSource());

/*

添加一条新的数据

*/

@Test

public void test01(){

// 定义SQL

String sql = "INSERT INTO emp(NAME,gender,salary)VALUES(?,?,?)";

// 执行

int i = jt.update(sql,"张三丰","男",90000);

System.out.println(i);

}

/*

更新一条数据

*/

@Test

public void test02(){

String sql = "update emp set salary=? where id=1";

int i = jt.update(sql,10000);

System.out.println(i);

}

/*

删除一条数据

*/

@Test

public void test03(){

String sql = "delete from emp where id=?";

int i = jt.update(sql,8);

System.out.println(i);

}

/*

* 查询一条数据返回map集合

* */

@Test

public void test04(){

String sql = "select * from emp where id=?";

Map<String,Object> map = jt.queryForMap(sql,1);

System.out.println(map);

}

/*

* 查询多条数据返回List集合

* */

@Test

public void test05(){

String sql = "select * from emp where id=? or id=?";

List<Map<String, Object>> list = jt.queryForList(sql,1,2);

System.out.println(list);

}

/*

* 查询多条数据返回List集合

* */

@Test

public void test06(){

String sql = "select * from emp where id=? or id=?";

List<Emp> list = jt.query(sql,new BeanPropertyRowMapper<Emp>(Emp.class),1,2);

System.out.println(list);

}

/*

* 聚合函数

* */

@Test

public void test07(){

String sql = "select count(id) from emp";

long l = jt.queryForObject(sql,Long.class);

System.out.println(l);

}

}

jdbc mysql url写法_MySQL第04篇:JDBC相关推荐

  1. jdbc mysql 换行符_mysql JDBC URL格式各个参数详解

    mysql JDBC URL格式如下: jdbc:mysql://[host:port],[host:port].../[database][?参数名1][=参数值1][&参数名2][=参数值 ...

  2. jdbc mysql emoji 读取_mysql+jdbc的emoji异常问题

    就是mysq支持emoji编码的问题,我已经按照这篇文章:mysql/Java服务端对emoji的支持所说的办法升级mysql和connector但问题还是没解决,希望高手指点. mysql 版本:5 ...

  3. php mysql存储过程写法_mysql存储过程写法

    都说不懂数据库的程序员不是合格的程序员,那么你知道MySQL存储过程应该怎么写吗? MySQL存储过程写法 可以使用 CREATE PROCEDURE 语句创建存储过程. 数据库存储过程语法格式如下: ...

  4. jdbc mysql是什么意思_什么是JDBC?

    展开全部 是跟数据库进行e68a8462616964757a686964616f31333431353265连接的时候,用来连接到指定远程数据库标识符. 可以在该URL中指定连接用户名和密码,同时,对 ...

  5. jdbc mysql数据库增删查改_通过JDBC对Mysql数据库进行简单的增删改查

    Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法.J ...

  6. jdbc mysql查询显示图片_在实现JDBC时如何显示存储引擎-MySQL CONNECTION查询?

    使用SELECT ENGINE显示存储引擎名称.让我们首先创建一个表-create table DemoTable -> ( -> Id int NOT NULL AUTO_INCREME ...

  7. mysql高效率写法_mysql高效率随机获取n条数据写法

    今天做项目遇到这个问题,本来想用mysql自带的随机函数来实现,但是想到这样做功能是实现了,但是效率真的好差!一下子想不到好的方法,就去网上找了一下,记录下来,好好研究学习一下. ID连续的情况下(注 ...

  8. mysql select 进阶_MySQL进阶_SELECT篇(一)

    MySQL中SELECT语句的基本语法是: SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [HIGH_PRIORITY] [DI ...

  9. mysql ndb 测试_Mysql性能2:基于JDBC的MySQL NDB性能测试结果

    测试场景: 硬件:2台HP G6(Host1和Host2) 操作系统:Suse10 SP2 软件:Host1上有一个Management Node,一个Data Node和一个Mysql Server ...

最新文章

  1. HTML5全屏API
  2. 别再用 httpClient了,快试试这款优雅的 HTTP 客户端工具!
  3. ORA-12541:TNS没有监听器
  4. 更改Mysql数据库存储位置的具体步骤
  5. 【bootstrap】使用支持bootstrap的时间插件daterangepicker
  6. python樱花代码_使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例
  7. 单片机机器周期怎么计算公式_单片机定时器周期计算公式
  8. swiftui 跳转_酷!苹果推出 SwiftUI,提高编程效率
  9. 差分进化算法原理及matlab代码实现
  10. Learn English !
  11. 谈谈我在自然语言处理入门的一些个人拙见
  12. JJavaBean中使用JDBC方式进行事务处理
  13. python考勤系统_python – 使用Django的考勤系统
  14. 通过CSS美化Web页面
  15. Postman使用详解
  16. 关于win10自带邮箱绑定163邮箱的设置
  17. 一个简单的文本编辑器。(是在DEV C++下写的)
  18. Gut | 复旦马延磊组揭示青年肠癌肠道菌群、代谢物及细菌酶基因特征
  19. 后台清理 清理cookie_清理枯木
  20. 面试时,问你有什么缺点,到底该怎么回答?我总结了“3个3”

热门文章

  1. 洞察CRM对企业的真正价值
  2. nutch2.3.1 scoring-opic 插件url评分为0 问题
  3. python成长之路第三篇(2)_正则表达式
  4. 七个小技巧保护无线网络安全
  5. oracle连接中出现错误ORA-12541,ORA-12514,ORA-01017的解决方法
  6. ztree在onCheck()方法中防止因触发联动关系导致页面多次渲染而卡死的问题
  7. js实现鼠标放在一级菜单,下滑出二级菜单
  8. C#中的 Stream
  9. npm -S -D -g i 有什么区别
  10. CocoaPods安装及使用