JDBC

JDBC

本系列为本人学习情况记录,部分资料来自老师课件或书籍摘录。


一、JDBC基本概念

  • 一种用于执行SQL语句的Java API
  • 可以为多种关系数据库提供统一访问
  • 由一组Java语言编写的类和接口组成

二、使用

2.1 连接驱动

数据库 驱动程序类 来源
MySQL com.mysql.jdbc.Driver com.mysql.cj.Driver (MySQL6.0 以上使用) mysql-connector-java-x.x.x.jar
Oracle oracle.jdbc.OracleDriver ojdbcx.jar
Access sun.jdbc.odbc.JdbcOdbcDriver JDK内置

注意:

  1. 这些类由JDBC使用,程序员并不会在程序中显式调用这些驱动类,所以必须编写代码告诉JVM加载它们
  2. Java 6 开始职称驱动程序的自动加载

2.2 连接到数据库

Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
数据库 驱动程序类
MySQL jdbc:mysql://localhost:3306/数据库名称(MySQL 8.0版本之前)
MySQL jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
Oracle jdbc:oracle:thin:@localhost:1521:数据库的SID
Access jdbc:odbc:数据源名称

2.3 JDBC访问数据库的基础代码

public class Main{
	public static void main(String[] args){
		//1.加载连接驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2.获得连接(连接到数据库) - 通过连接管理器创建连接对象
		Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		//3.通过连接对象获取语句对象
		Statement statement = connection.createStatement();

		//操作

		//执行完毕后,关闭打开的资源
		statement.close();
		connection.close();
	}
}

Statement 常用方法

方法 作用
int executeUpdate(String sql) 可以执行插入、删除、更新等语句,或者是不返回任何内容的SQL语句
boolean execute(String sql) 返回值为true时表示执行的是查询语句,可以通过getResultSet()获得结果集;返回值为false时执行的是更新语句或DDL语句
int getUpdateCount() 获取更新的纪录数量
ResultSet executeQuery(String sql) 执行SQL查询语句并返回ResultSet结果集对象

ResultSet常用方法

方法 作用
boolean next()/boolean previous() 将游标从当前位置向 下 / 上 移动一行
int getInt(int columnIndex)/int getInt(String columnLabel) 以整形方式获取结果集中指定列号或列名的值
String getString(int) / String getString(String) 以字符串方式获取结果集中指定列号或列名的值
Object getObject(int)/Object getObject(String) 以对象方式获取结果集中指定列号或列名的值

SQL 注入漏洞

一个有趣的安全漏洞:

//一个简单的登录语句
String sql = format("select * from table where account='%s' and loginPassword='%s';", account, loginPassword);
//假如参数为:
String account = '%(任意)';
String loginPassword = "' or true or '";

这样的情况发生后,参数带入语句结果为:

sql = select * from table where account='%(任意)' and loginPassword='' or true or '';

就发生了 SQL 注入漏洞

PreparedStatement

使用PreparedStatement类解决SQl 注入漏洞

String sql = "select * from Student where stuId=? and login_pwd=?;";
//1.声明时直接传递SQL语句
PreparedStatement statement = connection.prepareStatement(sql);
//2.预编译参数 - 需要在执行语句之前进行预编译
statement.setString(1, account);
statement.setString(2, password);
//3.执行时不再需要SQL语句
ResultSet resultSet = statement.executeQuery();

三、元数据

JDBC
JDBC

		DatabaseMetaData databaseMetaData = connection.getMetaData();
		System.out.println("连接URL:" + databaseMetaData.getURL());
		System.out.println("用户名:" + databaseMetaData.getUserName());
		System.out.println("连接驱动程序:" + databaseMetaData.getDriverName());
		System.out.println("连接驱动版本:" + databaseMetaData.getDriverVersion());
		System.out.println("数据库名称:" + databaseMetaData.getDatabaseProductName());
		System.out.println("数据库版本:" + databaseMetaData.getDatabaseProductVersion());
		
		System.out.println("数据库中使用的表的类型:");
		ResultSet resultSet = databaseMetaData.getTableTypes();
		while (resultSet.next()){
			System.out.println(resultSet.getString("table_type"));
		}
		
		//catalog 表所在数据库名
		//schemaPattern 表所在模式名称 null 就搜索所有
		//tableNamePattern 要搜索表名的通配符
		System.out.println("数据库中的表:");
		resultSet = databaseMetaData.getTables("schooldb", null, null, new String[] {"table", "view"});
		while (resultSet.next()){
			System.out.println(resultSet.getString("table_cat") + "\t" +
					resultSet.getString("table_schem") + "\t" +
					resultSet.getString("table_name") + "\t" +
					resultSet.getString("table_type") + "\t" +
					resultSet.getString("remarks")
			);
		}
		Statement statement = connection.createStatement();
		ResultSet rs = statement.executeQuery("select * from student");
		ResultSetMetaData metaData = rs.getMetaData();
		System.out.println("共有" + metaData.getColumnCount() + "列");
		for(int i = 1; i <= metaData.getColumnCount(); i++) {
			System.out.print("列名:" + metaData.getColumnName(i));
			System.out.print("\t是否自增列:" + metaData.isAutoIncrement(i));
			System.out.print("\t数据库名:" + metaData.getCatalogName(i));
			System.out.print("\t表名:" + metaData.getTableName(i));
			System.out.print("\t列类型:" + metaData.getColumnTypeName(i));
			System.out.println("\t是否可以为空:" + metaData.isNullable(i));
		}
上一篇:execute,executeQuery,executeUpdate的区别是什么?


下一篇:SimpleExecutor.doQuery()-ResultSetHandler 处理结果集