Java连接MySQL数据库,读取、遍历输出数据库查询结果ResultSet、使用“Class.forName(JDBC_DRIVER);”来注册加载驱动的原因

13 篇文章 2 订阅
11 篇文章 0 订阅

MySQL数据库简介

此处先给出MySQL官网?

Java对于数据库常用操作的封装

Java通过提供统一API定义的方式来实现对各种数据库进行操作时Java代码编码层面的统一,有效减少了Java代码在跨数据库时——Java项目在数据库需要变更时需要修改代码的问题。这样做的好处是显而易见的,①使操作不同的数据库在Java层面得到了统一,有利于Java项目实现跨数据库,当然变更数据库时,项目中要导入对应数据库的jar包②淡化不同数据库版本在Java代码中的差异,从而进一步突出Java项目中的业务逻辑。在使用Java的时候,不用关心底层使用什么数据库,只需要关心业务逻辑即可。API的具体实现由各数据库厂商自己提供(jar包,以驱动的形式)。在使用的时候,只需在自己的项目中导入对应数据库驱动的jar包即可,示意图如下所示。
在这里插入图片描述

目前常用的数据库种类很多,比如常见的MySQL、Oracle、SqlServer、Sqlite… 这些数据库都有自己的特性,如果Java为每一种数据库开发一套API,进行数据库操作,那么将是很头疼的,原因如下:  
1、每一种数据库都有差异,那么就代表每一套API的使用方法可能都不同;
2、不便于数据库迁移,比如,前期使用MySQL,到后期发现Oracle更加适合项目,于是将数据从MySQL迁移到Oracle中了,因为API不同,所以需要重新修改所有的SQL操作。
3、除此之外,这么多套API,维护起来也是很麻烦的;
在这里插入图片描述

连接、操作MySQL数据库用到的类

连接操作数据库过程中会用到的类,如下图所示。
在这里插入图片描述

Java工程 连接、操作数据库

下面每一行代码的含义补入本文 三、
补入本文,好好看!

  1. 首先将jar包mysql-connector-java-8.0.30.jar导入Java工程的正确位置,通常在lib目录下。Java工程导入jar包的方法详见这篇博客
  2. 设置JDBC驱动名和数据库URL,JDBC连接mysql数据库时默认使用IP地址127.0.0.1和端口号3306,所以当连接数据库与此一致时,可省略数据库地址和端口为jdbc:mysql:///test
     
    ①MySQL 8.0 以下版本 - JDBC 驱动名(即jar包中的名称),注册JDBC驱动及数据库 URL
    static final String JDBC_DRIVER = “com.mysql.jdbc.Driver”;
    static final String DB_URL = “jdbc:mysql://localhost:3306/test”;
     
    ②// MySQL 8.0 以上版本 - JDBC 驱动名(即jar包中的名称),注册JDBC驱动及数据库 URL
    static final String JDBC_DRIVER = “com.mysql.cj.jdbc.Driver”;
    static final String DB_URL = “jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC”;

因为本次使用的是mysql-connector-java-8.0.30.jar,如第一步中所述。若使用①中配置url,在第3步使用JDBC_DRIVER注册JDBC驱动时,会报如下错误Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

  1. 加载数据库驱动(即jar包中的名称),注册JDBC驱动:Class.forName(JDBC_DRIVER);

Class.forName(JDBC_DRIVER);来注册加载驱动的原因

Class.forName(类名)是让JVM查找并加载该类名对应的类中的静态代码块,而本文示例中使用的是MySQL数据库,所以选择com.mysql.jdbc.Driver类(MySQL数据库厂商提供的 JDBC 驱动,并借助于这些驱动连接数据库)中正好只有一段静态代码——使用Jdbc程序中的DriverManager来加载驱动,由此创建与数据库的链接,如下所示。
在这里插入图片描述

所以删除本句话及catch中本句,可能抛出的异常。

在实际开发中之所以推荐使用Class.forName(“com.mysql.jdbc.Driver”);,而非registerDriver方法,来注册驱动,这是因为:
如果代码中直接使用mysql的jar包中的DriverManager类中的方法,会使程序依赖mysql jar包的api并与所使用的数据库产生耦合,当项目程序要更换底层数据库时,因为脱离mysql的jar包导致程序无法编译等非常麻烦的问题。
但此方式有问题,因为若更换数据库了,Class.forName(“com.mysql.jdbc.Driver”);中的参数“com.mysql.jdbc.Driver”不需要变更吗???自认待确认

Class.forName(“com.mysql.jdbc.Driver”);的内容详见此博客

  1. 创建【并打开?(有博客提到,待确认)】到数据库的链接会用到的Connection对象,(其实就是创建了一个和数据库服务器进行连接的Socket(传输层,使用TCP)。当Java项目和数据库不在同一台机器上,还涉及到了网络IO,网络IO的速度并不快connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC", "root", "");

“jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC”:是mySql数据库的url,其中的test是数据库的名称,可通过net start mysql启动数据库、mysql -u root -p登录数据库后,在mysql>下(自认,即数据库内)使用show databases;查看当前电脑上现有数据库的所有名称。

  1. 创建【执行sql语句、负责对数据库进行操作】的对象:statement = connection.生成各类statement方法();,如下方备注所示。

statement = connection.createStatement();//返回Statement接口对象。此时查询结果java.sql.resultset只能一条条向下读,如果在代码中使用resultSet.beforeFirst();试图回滚到resultSet第一条时,会报错java.sql.resultset is type_forward_only。此时就需要使用带参数的构造方法,statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);以设置ResultSet回滚查询,但是sqlite数据库不支持回退模式,会报错提示
 
//
statement = connection.prepareStatement(...);//返回PreparedStatement接口对象,PreparedStatement继承自Statement
statement = connection.prepareCall(...);//返回CallableStatement接口对象,CallableStatement继承自PreparedStatement
 
Statement接口有两个子类,分别是PreparedStatement和CallableStatement:connection.prepareStatement(...)返回PreparedStatement对象和connection.prepareCall(...);返回CallableStatement对象。

  1. 编写要执行的sql语句,比如查询,请注意sql语句要以分号结尾String sqlString = "select * from hogwarts_user;";

使用show tables;来查看当前数据库test中的表(Tables_in_test)有哪些,如下图所示。
在这里插入图片描述

  1. 使用第5步中创建的“执行sql语句的对象”statement的对应方法来执行对应sql操作:比如本次选择使用statement.executeQuery(sqlString)来执行第6步中编写的SQL语句。
  • execute(String sql):方法声明为boolean java.sql.Statement.execute(String sql)。本方法可用来执行所有的SQL语句,本方法的返回值表示方法执行的SQL语句的类型——执行DML的SQL语句则返回false,执行DQL的SQL语句则返回true。
  • executeQuery(sqlString):方法声明为ResultSet executeQuery(String sql) throws SQLException;。本方法用来执行DQL的SQL语句,本方法的返回值是执行DQL的SQL查询的结果集。查询结果返回给“java.sql.ResultSet”:ResultSet resultSet = statement.executeQuery(sqlString);
  • executeUpdate(sqlString):方法声明为int executeUpdate(String sql) throws SQLException;。本方法用来执行DML的SQL语句,本方法的返回值是本次SQL操作中受影响的记录条数。
  1. 输出resultSet中的查询结果:如下所示。需要注意的是,java.sql.ResultSet也需要close()关闭
			//输出查询结果
			while (resultSet.next()) {
				int id = resultSet.getInt("id");//resultSet.getInt用于获取int类型的结果
				String nameString = resultSet.getString("name");//resultSet.getString用于获取String类型的结果
				String ageString = resultSet.getString("age");
				
				System.out.print("id是"+id);
				System.out.print(",name是"+nameString);
				System.out.println(",age是"+ageString);
				System.out.println("---------------");
			}

遍历输出MySQL查询结果java.sql.ResultSet

方法详见此博客

完整代码示例

完整代码,如下所示。

import java.sql.*;

Connection connection = null;
SavePoint sp = null;
Statement statement = null;
ResultSet resultSet = null;//java.sql.ResultSet也需要close关闭!

// MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
//    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
//    static final String DB_URL = "jdbc:mysql://localhost:3306/test";

// MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";  
    static final String DB_URL = "jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    
try{
	//通过Class.forName加载“com.mysql.cj.jdbc.Driver”类中的静态代码,来使用mysql数据库jar包中代码的方式,加载数据库驱动(即jar包中的名称),注册JDBC驱动。
	Class.forName(JDBC_DRIVER);
			
	//打开链接
	connection = DriverManager.getConnection(DB_URL, "root", "");
	//关闭事务自动提交
	//connection.setAutoCommit(false);//待确认提交事务的位置后,再解除此注释。
	//设置事务回滚点,java.sql.Connection 在创建回滚点时 需要 设置回滚点的名称。
	sp = connection.setSavepoint("begin");
	
	//创建sql查询
	statement = connection.createStatement();
	//sql语句
	String sqlString = "select * from hogwarts_user;";
	//执行查询,获取sql查询结果
	resultSet = statement.executeQuery(sqlString);
			
	//输出查询结果
	while (resultSet.next()) {//此循环条件自测无误,不会导致错过一条
		int id = resultSet.getInt("id");
		String nameString = resultSet.getString("name");
		String ageString = resultSet.getString("age");
				
		System.out.print("id是"+id);
		System.out.print(",name是"+nameString);
		System.out.println(",age是"+ageString);
		System.out.println("---------------");
	}
} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		
		//发生异常时,回滚事务
		try {
	        connection.rollback(sp);
        } catch (SQLException e1) {
        	e1.printStackTrace();
        }
		
} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		
		//发生异常时,回滚事务
		try {
	        connection.rollback(sp);
        } catch (SQLException e1) {
        	e1.printStackTrace();
        }
}finally {
	//此部分虽然保证了数据库的安全开启、关闭,但造成了大量时间开销,所以建议使用连接池实现对数据库的连接和操作
	if (resultSet!=null) {//java.sql.ResultSet也需要close!
		try {
			resultSet.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	if (statement!=null) {
		try {
			statement.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
			
	if (connection!=null) {
		try {
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Java工程 通过连接池实现连接、操作数据库

JDBC中使用连接时都要创建一个Connection对象,使用完毕后将其销毁,这种重复创建、销毁、创建、销毁…的过程是特别耗费计算机性能以及计算时间的,而数据库如果使用了数据库连接池,就能达到Connection对象的复用效果。
Java工程使用连接池实现连接、操作数据库详见此博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值