Java 通过JDBC操作mysql数据库


JDBC & MySql

一、什么是JDBC?

Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。它JDBC是面向关系型数据库的。

二、连接的步骤

准备工作
  • 下载mysql connnectors :在 https://dev.mysql.com/downloads/connector/j/下载
  • 然后导入jar包到IDE中 :
    • 方法:右击工程名->Build Path->Configure Build Path,选择Add External JAR… 找到如mysql-connector-java-5.1.31-bin.jar所在的位置,然后将驱动包加载到项目中。
1.标准步骤

注意:所有关于jdbc操作包的名称 全部 都是java.sql.xxx 原因请看注意事项。


package an.example.sql;

import java.sql.*;

public class ConnectSQL {

	// JDBC 驱动名及数据库 URL
	static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
	static final String DB_URL = "jdbc:mysql://localhost/web09?useUnicode=true&characterEncoding=utf-8&useSSL=false";

	// 数据库的用户名与密码,需要根据自己的设置
	static final String USER = "root";
	static final String PASS = "mysql";

	//
	public static void main(String[] args) {
		Connection conn = null;
		Statement stmt = null;
		try {
			// 注册 JDBC 驱动
			Class.forName("com.mysql.jdbc.Driver");

			// 打开链接
			System.out.println("连接数据库...");
			conn = DriverManager.getConnection(DB_URL, USER, PASS);

			// 执行查询
			System.out.println(" 实例化Statement对象...");
			stmt = conn.createStatement();
			String sql;
			sql = "SELECT * FROM users";
			ResultSet rs = stmt.executeQuery(sql);
			System.out.println();
			// 展开结果集数据库
			while (rs.next()) {
				// 通过字段检索

				String name = rs.getString(1);

				// 输出数据

				System.out.print("学生名称: " + name);

				System.out.print("\n");
			}
			// 完成后关闭
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException se) {
			// 处理 JDBC 错误
			se.printStackTrace();
		} catch (Exception e) {
			// 处理 Class.forName 错误
			e.printStackTrace();
		} finally {
			// 关闭资源
			try {
				if (stmt != null)
					stmt.close();
			} catch (SQLException se2) {
			} // 什么都不做
			try {
				if (conn != null)
					conn.close();
			} catch (SQLException se) {
				se.printStackTrace();
			}
		}
		System.out.println("Goodbye!");
	}
}
2.可防止sql注入的prepareStatment的使用

package com.newmore.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JdbcTest2 {
	public static void main(String[] args) throws Exception {
		String dbUrl="jdbc:mysql://192.168.144.139:3306/py3?useUnicode=true&characterEncoding=utf-8&useSSL=false";
		String user="root";
		String password="mysql";
		String Sno="200215121";
		//1.注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.获取链接
		Connection conn = DriverManager.getConnection(dbUrl, user, password);
		
		//3获取预处理语句
			//书写sql语句
		String sql="select * from Student where Sno=?";
		PreparedStatement ps = conn.prepareStatement(sql);
		//添加查询参数
		ps.setString(1, Sno);
		//4.执行sql查询
		ResultSet rs = ps.executeQuery();
		//5处理结果集
		while(rs.next()) {
			String name = rs.getString("Sname");
		
			
			String name3 = rs.getString(5);
			System.out.println(name+"\t"+name3);
		}
		//6关闭链接
		rs.close();
		ps.close();
		conn.close();
		
	}
}

三、原理剖析

Class.forName()装载类,在调用一个类的构造方法,初始化静态成员或者这个类有main方法时,JVM都会装载对应的类。首先我们就看看com.mysql.jdbc.Driver类做了什么事情,找到MYSQL-JDBC驱动源码,解压之后找到src目录,然后找到com.mysql.jdbc下的Driver.java类

1. package com.mysql.jdbc;  
2. import java.sql.SQLException;  
3. public class Driver extends NonRegisteringDriver implements java.sql.Driver {  
4.     static {  
5.         try {  
6.             java.sql.DriverManager.registerDriver(new Driver()); //1  
7.         } catch (SQLException E) {  
8.             throw new RuntimeException("Can't register driver!");  
9.         }  
10.     }  
11.     // ~ Constructors  
12.     // -----------------------------------------------------------  
13.     /** 
14.      * Construct a new driver and register it with DriverManager 
15.      *  
16.      * @throws SQLException 
17.      *             if a database error occurs. 
18.      */  
19.     public Driver() throws SQLException {  
20.         // Required for Class.forName().newInstance()  
21.     }  
22. }  

Driver类继承NonRegisteringDriver 同时实现接口java.sql.Driver
此类会有一个静态块

1. static {  
2.         try {  
3.             java.sql.DriverManager.registerDriver(new Driver()); //1  
4.         } catch (SQLException E) {  
5.             throw new RuntimeException("Can't register driver!");  
6.         }  
7.     }  

Class.forName的作用是要求JVM查找并加载指定的类, 也就是说JVM装载此类并执行静态块代码
此静态块只有一句关键部分,1处
在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC 驱动
的Driver类的代码都必须类似下面这段
java.sql.DriverManager.registerDriver(new Driver());
所以,如果你要自己实现一个数据库的JDBC驱动,那么就得实现java.sql.Driver接口,并且需要在实现类中使用java.sql.DriverManager.registerDriver(new Driver())注册自己,new Driver()就是创建一个Driver对象,所以此类会有一个无参数的构造函数:

1. public Driver() throws SQLException {  
2.  }  

下面再看看DriverManager.registerDriver()这个方法,源码如下:

1. public static synchronized void registerDriver(java.sql.Driver driver)  
2.     throws SQLException {  
3.     if (!initialized) {  
4.         initialize();  
5.     }  
6.         
7.     DriverInfo di = new DriverInfo();  
8.     di.driver = driver;  
9.     di.driverClass = driver.getClass();  
10.     di.driverClassName = di.driverClass.getName();  
11.     // Not Required -- drivers.addElement(di);  
12.     writeDrivers.addElement(di);   
13.     println("registerDriver: " + di);  
14.       
15.     /* update the read copy of drivers vector */  
16.     readDrivers = (java.util.Vector) writeDrivers.clone();  
17. }  

此方法是一个静态同步的方法,形式参数是java.sql.Driver接口类型,因为com.mysql.jdbc.Driver这个类实现了java.sql.Driver接口,所以com.mysql.jdbc.Driver实例对象new Driver()是可以作为实参传入到此方法中来的。在DriverManager类中都是使用的Driver接口类型,也就是说驱动的使用不依赖于任何实现。如果需要更换你所连接的数据库,只需要在Class.forName传入的参数换成另一个数据库的驱动类,但要求此类必须实现Driver接口。

四、一些注意事项

1.mysql 8.0及其以上版本的连接问题

8.0版本的mysql数据的连接 与 5.0的有所不同,下面直接贴出 8.0版本应该有的 jdbc驱动连接

内容如下 :

driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/beauty_ssm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
  • JDBC driver 由“com.mysql.jdbc.Driver”改为“com.mysql.cj.jdbc.Driver”。

  • JDBC url为:
    jdbc:mysql://localhost/rs_report?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT

  • 出现错误:“Establishing SSL connection withoutserver's identity verification is not recommended. According to MySQL 5.5.45+,5.6.26+ and 5.7.6+ requirements SSL connection must be established by defaultif explicit option isn't set. For compliance with existing applications notusing SSL the verifyServerCertificate property is set to 'false'. You needeither to explicitly disable SSL by setting useSSL=false, or set useSSL=trueand provide truststore for server certificate verification.”

解决方案,在url中加上“userSSL=true”或“userSSL=false”。

  • 出现错误:“java.sql.SQLException: The server time zonevalue '???ú±ê×??±??' is unrecognized or represents more than one time zone. Youmust configure either the server or JDBC driver (via the serverTimezoneconfiguration property) to use a more specifc time zone value if you want toutilize time zone support.”解决方案,在url中加上“serverTimezone=GMT”。
    导入包名的问题

java.sql包中的接口,它是sun公司为了简化,统一对数据库的操作,定义了一套java操作数据库的规范,由各个数据库公司自己实现,数据库有mysql oracle等,而com.mysql.jdbc包中的类是mysql自己实现规范接口的类,不同的数据库有不同的实现,为了能够只写一套代码,实现跨数据库使用,书写传统jdbc需要导入的包就使用java.sql包,而不用考虑具体的实现类。


文章作者: Bxan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bxan !
  目录