一、什么是JDBC?
概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库
二、JDBC本质
JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
三、JDBC快速入门
1.JDBC编程六步
第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
第二步:获取数据库连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL DML....)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
2.JDBC快速入门
package com.aynu.jdbc;
import cn.aynu.pojo.User;
import java.sql.*;
/**
* 查询tab_user表
*/
public class JDBCTest04 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet resultSet = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db",
"root",
"root");
// 3.获取数据库操作对象
stmt = conn.createStatement();
// 4.执行sql语句
String sql = "select * from tab_user";
resultSet = stmt.executeQuery(sql);
// 5.处理查询结果集
User u = new User();
while (resultSet.next()){
String id = resultSet.getString("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
Date birthday = resultSet.getDate("birthday");
u.setId(id);
u.setName(name);
u.setAge(age);
u.setBirthday(birthday);
System.out.println(u);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
四、详解JDBC各个对象
1.DriverManager
DriverManager:驱动管理对象
功能:
1.注册驱动:告诉程序使用的对应数据库的驱动
代码:Class.forName("com.mysql.jdbc.Driver");
源码分析:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
2.获取数据库连接
方法:static Connection getConnection(String url, String user, String password)
参数:
url:指定连接的路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db
user:用户名(mysql数据库的用户名)
root:密码(mysql数据库的密码)
2.Connection
Connection:数据库连接对象
获取方法:conn = DriverManager.getConnection(url, user, password);
功能:
1.获取执行sql语句的对象
conn.createStatement()
conn.prepareStatement(sql);
2.管理事务
开启事务:conn.setAutoCommit(false);
提交事务:conn.commit();
事务回滚:conn.rollback();
注意:此处的conn代指Connection对象
3.Statement
Statement:执行sql的对象
获取方法:Statement stmt = conn.createStatement();
1. 执行sql
1. boolean execute(String sql) :
可以执行任意的sql
2. int executeUpdate(String sql) :
可以执行DML(insert、update、delete)语句、
DDL(create,alter、drop)语句
* 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功
* 返回值>0的则执行成功,反之,则失败。
3. ResultSet executeQuery(String sql) :
执行DQL(select)语句
4.ResultSet
ResultSet:结果集对象,封装查询结果
获取方法:ResultSet resultSet = stmt.executeQuery(sql);
boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),
如果是,则返回false,如果不是则返回true
* getXxx(参数):获取数据
* Xxx:代表数据类型 如: int getInt() , String getString()
* 参数:
1. int:代表列的编号,从1开始 如: getString(1)
2. String:代表列名称。 如: getDouble("balance")
while (resultSet.next()){
// 获取数据库中该行的数据
String id = resultSet.getString("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
Date birthday = resultSet.getDate("birthday");
}
5. PreparedStatement
PreparedStatement:执行sql的对象(预编译对象)
获取方法:PrepareStatement pstmt = conn.prepareStatement(sql);
1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。
会造成安全性问题
2 解决sql注入问题:使用PreparedStatement对象来解决
2. 预编译的SQL:参数使用?作为占位符
package com.aynu.jdbc;
import java.sql.*;
import java.util.Scanner;
/**
* 练习使用PreparedStatement
* 实现登录功能id name
*/
public class JDBCTest05 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/day04",
"root", "root");
// 3.获取数据库操作对象
// 定义sql语句
String sql = "select * from tab_user where id = ? and name = ?";
pstmt = conn.prepareStatement(sql);
System.out.print("id:");
String id = new Scanner(System.in).nextLine();
System.out.print("name:");
String name = new Scanner(System.in).nextLine();
// 给?赋值
pstmt.setString(1, id);
pstmt.setString(2, name);
// 4.执行sql语句
resultSet = pstmt.executeQuery();
// 5.处理查询结果集
if (resultSet.next()){
System.out.println("登陆成功");
} else{
System.out.println("登陆失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pstmt != null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
五、提取工具类
仅由以上两个代码案例可以明显看出,JDBC代码并不复杂,但是重复代码非常多,所以我们有必要抽取一个工具类,下面是我在本阶段的学习中抽取的一个工具类,和配置文件(将driver,url,user,password抽取到一个properties中),大家也可以拿去使用。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8
user=root
password=root
注意:在日常学习中
?useUnicode=true&characterEncoding=utf-8user=root
是为了处理中文乱码问题
package com.aynu.util;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具类
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 静态代码块,用来加载配置文件
*/
static {
try {
Properties pro = new Properties();
String path = Thread.currentThread().getContextClassLoader().getResource("jdbc.properties").getPath();
pro.load(new FileInputStream(path));
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
// 注册驱动
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();
}
}
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs,Statement stmt, Connection conn){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}