JDBC是Java程序访问数据库的标准,由一组Java语言编写的类和接口组成,这些类和接口称为JDBC API
JDBC API包括两个包
- java.sql包:基本的数据库编程服务的类和接口建立与数据库的连接
- javax.sql包:主要提供了服务器端访问和处理数据源的类和接口
JDBC的基本功能包括
- 建立与数据库的连接
- 发送SQL语句
- 处理数据库操作结果
JDBC(Java DataBase Connectivity) 驱动可以为多种关系型数据库DBMS 提供统一的访问方式,用Java来操作数据库
涉及知识点,下面实例要用
数据库驱动
DB | 驱动(jar包) | 具体驱动类 | 连接字符串 |
---|---|---|---|
MySQL | mysql-connector-java-x.jar | com.mysql.jdbc.Driver | jdbc:mysql://localhost:3306/数据库实例名 |
SqlServer | sqljdbc-x.jar | com.microsoft.sqlserver.jdbc.SQLServerDriver | bc:microsoft:sqlserver:localhost:1433;databasename=数据库实例名 |
Oracle | ojdbc-x.jar | oracle.jdbc.OracleDriver | jdbc:oracle:thin:@localhost:1521:数据库实例名 |
MySQL驱动包6及以上具体驱动类改为com.mysql.cj.jdbc.Driver,具体可直接在导入的jar包中查看。
使用JDBC操作数据库时,如果对数据库进行了更换,只需要替换:驱动、具体驱动类、连接字符串、DB实例名、用户名、密码。
驱动包可以去中央仓库maven下载:https://mvnrepository.com/
Statement操作数据库:
- 增删改:executeUpdate()
- 查询:executeQuery()
JDBC API:https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html
JDBC驱动建立与数据库的连接流程:
- 导相应数据库的驱动:jar包
- 反射class.forName()加载具体的驱动类
- DriverManager.getConnection()管理JDBC驱动并与数据库建立连接
- Statement(PreparedStatement/createStatement/CallableStatement)获取操作数据库的对象
- Statement操作数据库: (增删改/查)处理结果集
- 关闭建立的对象
下面以MySQL数据库为例,与Java建立连接
准备一个mysql数据库:SYMYSQL
并建立一张表:student
下方案例用CMD操作DB,启动mysql,也可以在电脑“服务”中启动
Java程序:
com.demo包下的JDBCPreparedStatementDemo.java
package com.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
public class JDBCPreparedStatementDemo {
private static final String URL = "jdbc:mysql://localhost:3306/SYMYSQL"; //mysql连接字符串,数据库名为SYMYSQL
private static final String USERNAME = "root"; //数据库用户名为root
private static final String PWD = "root"; //数据库密码为root
// 增删改
public static void update() {
Connection connection = null;
PreparedStatement pstmt = null;
try {
// a.导入驱动,加载具体的驱动类
Class.forName("com.mysql.jdbc.Driver"); // 加载mysql具体的驱动类
// b.与数据库建立连接
connection = DriverManager.getConnection(URL, USERNAME, PWD);
/*
// Statement
stmt = connection.createStatement();
String sql = "insert into student values(8,'suoyue',56)"; //DB插入语句
//String sql = "update student set stuScore='66' where stuNum=8"; //DB更新语句
//String sql = "delete from student where stuNum=8"; //DB删除语句
int count = stmt.executeUpdate(sql); // 返回值表示 增删改 几条数据
*/
// PreparedStatement
String sql = "insert into student values(?,?,?)"; //数据库插入语句
//String sql = "update student set stuScore=? where stuNum=?"; //DB更新语句
//String sql = "delete from student where stuNum=?"; //DB删除语句
pstmt = connection.prepareStatement(sql); //预编译
//赋值操作:配置占位符数据[8,"suoyu",56]
pstmt.setInt(1, 8);
pstmt.setString(2, "suoyu");
pstmt.setInt(3, 56);
int count = pstmt.executeUpdate(); // 增删改,成功返回:1,失败返回:0
// d.处理结果
if (count > 0) {
System.out.println("操作成功");
}
} catch (ClassNotFoundException e) { //Class.forName() 抛出ClassNotFoundException异常
e.printStackTrace();
} catch (SQLException e) { //其余方法全部抛SQLException异常
e.printStackTrace();
} catch (Exception e) { //保险起见,只要有异常就再抛个Exception异常
e.printStackTrace();
} finally {
try {
if (pstmt != null) //先判断不为空再进行关闭操作,避免异常
pstmt.close();
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/*
//查
public static void query() {
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
......
String sql = "select count(*) from login where stuNum= ? and stuName =?";
pstmt = connection.prepareStatement(sql);
pstmt.setInt(1, 8);
pstmt.setString(2, "suoyue");
rs = pstmt.executeQuery(); // 执行SQL(增删改executeUpdate(),查询executeQuery())
int count = -1;
if (rs.next()) { //next()光标下移,判断是否有下一条数据;true/false
count = rs.getInt(1); //getXxx(字段名|位置):获取具体的字段值
}
if (count > 0) {
System.out.println("查找成功");
} else {
System.out.println("查找失败");
}
}
......
}
*/
public static void main(String[] args) {
update() ;
// query();
}
}
在PreparedStatement与createStatement的使用中推荐使用前者,原因如下:
- 编码更加简便(避免了字符串的拼接)
- 提高性能(因为有预编译操作,预编译只需要执行一次)
- 安全(可以有效防止sql注入)
CallableStatement:调用 存储过程、存储函数
封装-通用类
package com.cn.dao.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtil {
static {
// 1.加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 通用的增删改操作
public static int executeUpdate(String sql, Object... objects) {
int rows = -1;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 2得到Connection接口指向的对象
conn = JdbcUtil.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
ps.setObject((i + 1), objects[i]);
}
rows = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeAll(rs, ps, conn);
}
return rows;
}
// 得到数据库连接
public static Connection getConnection() {
Connection conn = null;
try {
// 2得到Connection接口指向的对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/gmshop", "root", "root");
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
// 关闭资源 Statement 父类 PreparedStatement 子类
public static void closeAll(ResultSet rs, Statement state, Connection conn) {
// 关闭资源
// 扑鱼:先撒网,再判断是否有鱼
// 先判断有鱼,再试图撒网扑鱼
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (state != null) {
try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}