1、jdbc简介
什么是jdbc
- Java Data Base Connectivity:java数据库连接
jdbc作用
- 通过jdbc可以让java程序操作数据库
jdbc的本质
- 官方定义的一套操作所有关系型数据库的规则,即接口(API)
- 各个数据库厂商去实现这个接口,提供数据库驱动jar包
- 我们可以使用这套接口编程,真正执行的代码时驱动jar包中的实现类
jdbc的好处
- 我们只需要会调用jdbc接口中的方法即可,使用简单
- 使用同一套java代码,进行少量的修改就可以访问其他jdbc支持的数据库了
2、jdbc API介绍
jdbc四个核心对象
对象 | 说明 |
---|---|
DriverManager | 用于注册驱动 |
Connection | 表示数据库的连接 |
Statement | 执行SQL语句对象 |
ResultSet | 结果集或一张虚拟表 |
jdbc使用步骤
- 注册驱动
- 获取数据库连接
- 获取执行SQL语句对象
- 执行SQL语句并返回结果
- 处理结果
- 释放资源
3、jdbc注册驱动
在使用jdbc之前我们需要导入jar包
注册驱动API
java.sql.DriverManager类用于注册驱动,提供如下方法注册驱动
static void registerDriver(Driver driver) 向DriverManager注册给定驱动
代码示例:
public static void main(String[] args) throws SQLException {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
}
注意:
- MySQL5之后的驱动包,可以省略注册驱动的步骤
- 自动加载jar包中META-INF/services/java.sql.Dreiver文件中的驱动类
4、Connection连接
Connection介绍
表示Java程序与数据库之间的连接,只有拿到Connection才能操作数据库
DriverManager类中的静态方法 | 描述 |
---|---|
static Connection getConnection(String url, String user, String password) | 连接到给定数据库URL,并返回连接 |
==参数说明:==
- String url:连接数据库的url,用于说明连接数据库的位置
- String user:数据库的账号
- String password:数据库的密码
连接数据库的URL地址格式:协议名:子协议://服务器名或IP地址:端口号/数据库名
以MySQL来写:
/**
* 1、协议名:jdbc
* 2、子协议:mysql
* 3、服务器名(本地):localhost
* 4、端口号:3306
* 5、数据库名:db1
**/
jdbc:mysql://localhost:3306/db1
获取Connection对象
public class Main {
public static void main(String[] args) throws SQLException {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2、获取数据库连接
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false", "root", "123456");
}
}
5、Statement对象
获取Statement对象
在java.sql.Connection接口有如下方法获取到Statement对象
Statement createStatement()
创建一个Statement对象来将SQL语句发送到数据库
案例代码
public class Main {
public static void main(String[] args) throws SQLException {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2、获取数据库连接
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false", "root", "123456");
//3、获取运送SQL的对象
Statement state = cn.createStatement();
}
}
6、JDBC实现对单表数据增删改操作
准备数据
CREATE TABLE USER (
id INT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(50),
PASSWORD VARCHAR(50)
);
INSERT INTO `user` VALUES
(NULL,'admin','123'),
(NULL,'test','123'),
(NULL,'gm','123');
CREATE DATABASE day17;
INSERT INTO USER VALUES(NULL,'weipeng','123');
6.1、使用Statement对象来执行SQL语句
API介绍
API | 说明 |
---|---|
ResultSet executeQuery(String sql) | 用于执行查询语句,返回查询到的结果集合 |
int executeUpdate(String sql) | 用于执行除查询外的SQL;返回影响的行数 |
==代码案例:==
public class demo01 {
public static void main(String[] args) throws SQLException {
/**
* 1、注册驱动
* 2、获取Connection连接
* 3、执行Statement
* 4、执行sql语句
* 5、处理结果
* 6、释放资源
*/
//1、注册驱动
DriverManager.registerDriver(new Driver());
//2、获取Connection连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
//执行Statement
Statement statement = connection.createStatement();
//定义sql语句
String sql = "INSERT INTO USER VALUES(NUll,'xiao ','123');";
//4、执行sql语句,返回影响函数
int row = statement.executeUpdate(sql);
System.out.println(row);
//5、关闭资源
statement.close();
connection.close();
}
}
6.2、ResultSet查询数据库
ResultSet原理
ResultSet用于保存执行查询SQL语句的结果,我们不能一次性取出所有的数据,需要一行一行的取出。
ResultSet内部有一个指针,记录获取到哪行数据
获取查询结果
boolean next() 将光标从当前位置向前移动一行,判断当前行是否有效
返回值
true :有效行,当前行有数据
false:无效行,当前行没有数据
get(参数):获取数据
数据类型:如 int getInt(参数);String getString(参数)
参数: String 列的名称
案例代码
public class demo02 {
public static void main(String[] args) throws Exception {
// 1、注册驱动
DriverManager.registerDriver(new Driver());
// 2、创建连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false"
, "root", "123456");
// 3、获取Statement对象
Statement statement = connection.createStatement();
//编写SQL语句
String sql = "select * from user;";
//执行sql
ResultSet resultSet = statement.executeQuery(sql);
//循环输出结果集合
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String password = resultSet.getString("password");
System.out.println("id="+ id + ",name=" + name + ",password="+ password);
}
//关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
6.3、查询结果封装对象
对象关系映射介绍
- 表 ----> 类
- 字段 ----> 成员变量
- 一条记录 ----> 一个对象
案例
- 先创建一个与数据库一一对应的实体类
- 再查询数据并进行封装
案例代码
- 实体类(字段要与mysql表一一对应,自行添加构造方法)
public class user {
private int id;
private String name;
private String password;
}
- 测试类
public class demo03 {
public static void main(String[] args) throws SQLException {
//1、注册驱动
DriverManager.registerDriver(new Driver());
//2、创建连接
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
//3、获取Statement对象
Statement statement = connection.createStatement();
//4、编写SQL语句
String sql = "select * from user;";
//5、执行SQL
ResultSet resultSet = statement.executeQuery(sql);
//6、创建集合
ArrayList<user> list = new ArrayList<>();
//7、循环遍历结果
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String password = resultSet.getString("password");
user newUser = new user(id, name, password);
list.add(newUser);
}
//8、遍历集合
for (user user : list) {
System.out.println(user);
}
//9、关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
7、JDBC中使用事务
数据准备
create table account(
id int primary key auto_increment,
name varchar(10),
balance double
);
insert into account(name, balance) values ('张三',1000),('李四',1000);
JDBC事务API
Connection接口中与事务有关的方法
方法名 | 说明 |
---|---|
void setAutoCommit(boolean autoCommit) | false:开始事务,true:关闭事务 |
void commit() | 提交事务 |
void rollback | 回滚事务 |
使用步骤:
- 注册驱动
- 获取连接
- 开启事务
- 获取到Statement
- Statement执行SQL
- 提交或回滚事务
- 关闭资源
案例代码
public class demo04 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
//1、注册驱动
DriverManager.registerDriver(new Driver());
//2、获取连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false",
"root", "123456");
//3、开启事务
connection.setAutoCommit(false);
//4、获取到Statement
statement = connection.createStatement();
//5、执行sql,张三借给李四500
statement.executeUpdate("update account set balance = balance - 500 where name = '张三'");
statement.executeUpdate("update account set balance = balance + 500 where name = '李四'");
//6、提交事务
connection.commit();
System.out.println("执行成功");
} catch (Exception e) {
try {
//失败回滚事务
if (connection != null){
connection.rollback();
}
System.out.println("执行失败");
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
} finally {
//关闭资源
try {
if (statement != null){
statement.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
try {
if (connection != null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
8、JDBC编写登录案例
用户输入账号和密码,有则登录成功,没有则失败
public class demo05 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号");
String name = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
pdUser(name,password);
}
public static void pdUser(String name,String password){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
DriverManager.registerDriver(new Driver());
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from user where NAME = '" + name +"' and PASSWORD = '" + password +"';");
if (resultSet.next()){
System.out.println("登录成功");
} else {
System.out.println("账号或密码错误");
}
} catch (Exception e) {
try {
resultSet.close();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
try {
statement.close();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
try {
connection.close();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
}
}
注意:
- 上面的代码中,SQL语句中我们使用拼接的方式,所以存在SQL注入的风险
- 所以我们需要去改进SQL语句
8.1、PreparedStatement使用
PreparedStatement使用格式
- SQL语句中的参数使用?作为占位符
- 给?占位符赋值
设置参数
- setXxx(参数1,参数2) ;Xxx代表数据类型
- 参数1:第几个
- 参数2:?的实际参数
执行SQL语句
- int executeUpdate();执行insert、update、delete语句
- ResultSet executeQuery();执行select语句
改进登陆案例
public class demo05 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号");
String name = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
pdUser(name,password);
}
public static void pdUser(String name,String password){
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
try {
DriverManager.registerDriver(new Driver());
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
String sql = "select * from user where name = ? and password = ?;";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,name);
preparedStatement.setString(2,password);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
System.out.println("登录成功");
} else {
System.out.println("账号或密码错误");
}
} catch (Exception e) {
try {
if (resultSet != null){
resultSet.close();
}
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
try {
preparedStatement.close();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
try {
connection.close();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
}
}
9、数据库连接池
数据库连接池简介
连接池概念:连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的
连接池原理:
- 启动数据库,连接池会初始化一些连接
- 当用户需要使用数据库连接,直接从连接池中取出
- 当用户使用完连接,会将连接重新放回连接池中
常用连接池介绍
javax.sql.DataSource表示数据库连接池,是JDK中提供的一个接口,没有具体的实现,它的实现是由连接池的厂商去实现,我们只需要学习这个工具即可
public interface DataSource{
Connection getConmection();
}
常用的连接池实现组件:
- 阿里巴巴-德鲁伊Druid连接池:Druid是阿里巴巴开源平台上的项目
- C3P0是一个开源的连接池,目前使用它的开源项目有Hibernate,Spring等
- DBCP(DataBase Connection Pool)数据库连接池,是Tomcat使用的连接池组件
9.1、Druid连接池
Druid常用 的配置参数
方法名 | 说明 |
---|---|
initialSize | 刚启动连接池时,连接池中包含连接的数量 |
maxActive | 连接池中最多可以放多少个连接 |
maxWait | 获取连接时最大等待时间,单位毫秒 |
Druid连接池使用步骤
- 导入druid的jar包
- 设置properties文件
- 加载properties文件到Properties对象中
- 创建Druid连接池,使用配置文件中的参数
- 从Druid连接池中取出连接
- 执行SQL语句
- 关闭资源
案例代码
public class demo7 {
public static void main(String[] args) throws Exception {
//加载properties文件的内容到Properties对象中
Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("src\\druid.properties");
properties.load(fileInputStream);
//创建连接池,使用配置文件中的参数
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//取出连接
Connection connection = dataSource.getConnection();
//执行sql语句
String sql = "insert into user values(null,?,?);";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"小陈");
preparedStatement.setString(2,"1234");
int row = preparedStatement.executeUpdate();
System.out.println(row);
//释放资源
preparedStatement.close();
//使用连接池之后,这里不是关闭,而是放回连接池
connection.close();
}
}
9.2、抽取工具类
package com.mysql.test;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class getUtils {
public static DataSource dataSource = null;
static {
try {
Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream("src\\druid.properties");
properties.load(inputStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}