JDBC驱动实现程序与数据库的连接

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();
			}
		}
	}
}
end
  • 作者:suoyue_zhan(联系作者)
  • 发表时间:2020-09-05 22:45:17
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接
  • 公众号转载:请在文末添加作者公众号二维码(公众号二维码见右边,欢迎关注)
  • 评论