JDBC概念

数据库实现了数据的持久化,但我们最终要在程序里处理数但我们最终要在程序里处理数据啊,那java代码中怎么去访问数据库读写数据呢?

这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:mysql驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以对数据库进行操作了。

Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。

Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。

调用方式有三种:

  • Statement语句
  • PreparedStatement预处理语句
  • CallableStatement存储过程

推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。
在这里插入图片描述

JDBC下载安装

mysql官网地址:https://www.mysql.com
jdbc下载地址:https://dev.mysql.com/downloads/connector/j/

下载JDBC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

安装JDBC

解压JDBC压缩包,放在项目的lib(自己创建)文件夹下
在这里插入图片描述
解压后文件中的jar包添加到依赖中
在这里插入图片描述

详细步骤

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args)
            throws ClassNotFoundException, SQLException {
        //通过java访问mysql数据库
        //这个对象获取数据库链接
        //注册驱动,输入链接地址,用户名,密码
        String driver = "com.mysql.cj.jdbc.Driver";
        
        //访问本机的mysql数据库,格式 jdbc:数据库://本地端口3306/数据库名?跨时区参数
        String url = "jdbc:mysql://localhost:3306/mysql-db?serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "root";

        Class.forName(driver);
        
        //获取到数据库链接
        Connection connection = DriverManager.getConnection(url, username, password);
        
        //创建一个Statement语句对象
        Statement stat = connection.createStatement();
        
        //执行SQL语句
        String sql = "select * from student";
        
        //把查询的结果(表记录)存放到ResultSet对象中,结果集
        ResultSet resultSet = stat.executeQuery(sql);
	}
}

mysql 8.0(oracle)把驱动包路径改了 驱动包(driver)地址:
8.0 之前。com.mysql.jdbc.Driver
8.0 之后。com.mysql.cj.jdbc.Driver
核心代码也改了,在数据库后面增加参数
时区参数:"?serverTimezone=Asia/Shanghai"

常用数据库URL地址的写法:

  • Oracle:jdbc:oracle:thin:@localhost:1521:mysql-db
  • SqlServer:jdbc:microsoft:sqlserver://localhost:1433;
    DatabaseName=mysql-db
  • MySql:jdbc:mysql://localhost:3306/mysql-db

Connection对象

可以通过对象DriverManager或者DataSource中的getConnection()方法拿到Connection对象,获取到数据库链接。

创建方式:

Connection connection = DriverManager.getConnection(url,user,pass); 
Connection connection = DataSource.getConnection(); 

JDBC1.0使用DriverManager类来产生一个对数据源的连接,相对于DriverManager,
JDBC2.0提供的DataSource接口是一个更好的连接数据源的方法。无需硬性编码驱动,对连接池的支持

三种执行对象:用于将 SQL 语句发送到数据库中

createStatement

  • 作用:用于执行不带参数的简单 SQL 语句
  • 特点:每次执行 SQL 语句,数据库都要执行 SQL 语句的编译,仅执行一次查询并返回结果的情形建议使用这个,此时效率高于 PreparedStatement

静态执行对象创建createStatement

Statement createStatement()
创建一个 Statement 对象来将 SQL 语句发送到数据库。
-
Statement createStatement(int resultSetType, int resultSetConcurrency)
创建一个 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
-
Statement createStatement(int resultSetType, int resultSetConcurrency, int
resultSetHoldability)

创建一个 Statement 对象,该对象将生成具有给定类型、并发性和可保存性的 ResultSet 对象。


PreparedStatement

  • 作用:用于执行带 或 不带参数的预编译 SQL 语句
  • 特点:是预编译的, 在执行可变参数的一条 SQL 语句时,比 Statement 的效率高,安全性好,有效防止 SQL 注入等问题,对于多次重复执行的语句,效率会更高

动态执行对象创建prepareStatement

PreparedStatement prepareStatement(String sql)
创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。
-
PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
创建一个默认 PreparedStatement 对象,该对象能获取自动生成的键。
-
PreparedStatement prepareStatement(String sql, int[] columnIndexes)
创建一个能返回由给定数组指定的自动生成键的默认 PreparedStatement 对象。
-
PreparedStatement prepareStatement(String sql, String[] columnNames)
创建一个能返回由给定数组指定的自动生成键的默认 PreparedStatement 对象。
-
PreparedStatement prepareStatement(String sql, int resultSetType, int
resultSetConcurrency)

创建一个 PreparedStatement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
-
PreparedStatement prepareStatement(String sql, int resultSetType, int
resultSetConcurrency, int resultSetHoldability)

创建一个 PreparedStatement 对象,该对象将生成具有给定类型、并发性和可保存性的 ResultSet 对象。


CallableStatement

  • 作用:用于执行对数据库存储过程 的调用

执行SQL语句

Statement对象常用方法:

方法内容
executeQuery(String sql)用于向数据发送查询语句。
executeUpdate(String sql)用于向数据库发送insert、update或delete语句
execute(String sql)用于向数据库发送任意sql语句
addBatch(String sql)把多条sql语句放到一个批处理中。
executeBatch()向数据库发送一批sql语句执行。

获取结果(ResultSet)

Jdbc中的ResultSet封装了Sql语句的执行结果集。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的指针。初始的时候,索引值是从1开始(数据库要求)指针指向第一个数据。调用ResultSet.next() 方法,使指针指向下一个数据,可以判断下个数据是否为空,或者可以调用getObject(int index)、getString(int index)等方法来获取指向的数据。

获取行

ResultSet提供了对结果集进行指针的方法:

方法内容
next()移动到下一行
Previous()移动到前一行
absolute(int row)移动到指定行
beforeFirst()移动resultSet的最前面。
afterLast()移动到resultSet的最后面。

获取值

ResultSet封装的数据通过get方法取出:

方法内容
getObject(int index)通过下标获取任意类型的数据
getObject(string columnName)通过列名获取任意类型的数据
getString(int index)通过下标获取指定类型的数据
getString(String columnName)通过列名获取指定类型的数据

事务:Connection提供了对于事务相关操作的支持

支持事务的数据库一般都有自动提交,提交、回滚、保存点、事务隔离级别这几个基本属性。

boolean getAutoCommit()
获取此 Connection 对象的当前自动提交模式。

void commit()
使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。

void rollback()
取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。

void rollback(Savepoint savepoint)
取消所有设置给定 Savepoint 对象之后进行的更改。

void setAutoCommit(boolean autoCommit)
将此连接的自动提交模式设置为给定状态。

void setTransactionIsolation(int level)
试图将此 Connection 对象的事务隔离级别更改为给定的级别。

int getTransactionIsolation()
获取此 Connection 对象的当前事务隔离级别。

Savepoint setSavepoint()
在当前事务中创建一个未命名的保存点 (savepoint),并返回表示它的新 Savepoint 对象。

Savepoint setSavepoint(String name)
在当前事务中创建一个具有给定名称的保存点,并返回表示它的新 Savepoint 对象。

void releaseSavepoint(Savepoint savepoint)
从当前事务中移除指定的 Savepoint 和后续 Savepoint 对象。

释放资源

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。后创建的对象先关闭,先关闭Statement对象再关闭Connection对象。


实践测试

通过SpringBoot项目中的测试类进行测试,数据源datasource已经在application.properties文件中配置,更多配置信息可参考博文https://blog.csdn.net/weixin_53601359/article/details/114416191

//通过元数据让查询映射更加灵活
@Test
    void testSelectNotices() throws SQLException {
    
   		//1.建立连接
        Connection connection = dataSource.getConnection();
        
        String sql = "SELECT id ,title,TYPE,content,STATUS,createdTime,modifiedUser,modifiedTime FROM sys_notice where id>=?;";
        
       //通过PrepareStatement创建Statement,可以动态传入sql中的"?",增加安全性灵活性。
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        
		//通过setInt方法为sql中第一个"?"赋值为2。
		//第一个参数为sql中的第几个"?"。第二个参数为对应的"?"赋值,类型和方法对应,例如:String类型参数用setString()方法。
        preparedStatement.setInt(1, 2);
        
        //执行sql,返回值为boolean,判断是否接受到数据(并不能判断执行是否成功,只能判断是否是查询语句),
        boolean flag = preparedStatement.execute();
		
		//创建结果集对象,用来接受数据库传过来的数据和元数据(元数据 = 表字段)
        ResultSet resultSet = null;
        
        if (flag) {
        	//通过preparedStatement.getResultSet()获取结果集(二维表结构)。
            resultSet = preparedStatement.getResultSet();

			//建立List集合存储数据,把每一条行数据存储在一个Map中
            List<Map<String, Object>> list = new ArrayList<>();
			
			///通过resultSet对象获取数据库中的元数据(表字段)
            ResultSetMetaData metaData = resultSet.getMetaData();

			//通过next()判断是否表中还有下一行数据(指针技术)
            while (resultSet.next()) {
            
            	//一行数据对应一个Map对象(行映射)
                Map<String, Object> map = new HashMap<>();
				
				//将取出来的数据存储到Map中(key为元数据"字段",value为每一行对应字段的数据)
				//getColumnCount()获取表字段的总数
                for (int i = 1; i < metaData.getColumnCount(); i++) {
                    map.put(metaData.getColumnLabel(i), resultSet.getObject(i));
                }
                
                //将每一行数据的Map对象存储到List集合中
                list.add(map);
            }
            
            //释放资源,后开启的先关闭
            resultSet.close();
            preparedStatement.close();
            connection.close();
			
			//通过foreach遍历List中的数据
            for (Map<String, Object> lists : list) {
                for (String key : lists.keySet()
                ) {
                    System.out.print(lists.get(key));
                }
                System.out.println();
            }
        }
    }

看到这里,就连单表查询都需要这么多代码,是不是感觉通过JDBC对数据库操作过于繁琐。所以诞生了Mybatis框架,Mybatis是一个优秀的持久层框架,底层基于JDBC实现与数据库的交互。并在JDBC操作的基础上做了封装和优化,它借助灵活的SQL定制,参数及结果集的映射方式,更好的适应了当前互联网技术的发展。在这里插入图片描述
了解Mybatis可参考博文:https://blog.csdn.net/weixin_53601359


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐