10JDBC

1. JDBC简介

  • JDBC是一套用于执行SQL语句的Java API,应用程序可通过这套API连接到关系型数据库,并使用SQL语句完成对数据库中数据的查询、增删改等操作
  • 不同种类的数据库(如MySQL、Oracle等)在内部处理数据的方式是不同的,如果使用数据库厂商提供的访问接口操作数据库,应用程序可移植性就会变得很差。JDBC要求各个数据库厂商按照统一的规范提供数据库驱动,而在程序中由JDBC和具体的数据库驱动联系,所以用户就不必直接与底层的数据库交互,这使得代码的通用性更强

在这里插入图片描述

  • JDBC在应用程序与数据库之间起到了一个桥梁作用,当应用程序使用JDBC访问特定的数据库时,需要通过不同数据库驱动与不同的数据库进行连接,连接后即可对数据库进行相应的操作。

  • 使用时需导入的jar包

    <dependency>
    	<groupId>mysql</groupId>
    	<artifactId>mysql-connector-java</artifactId>
    	<version>8.0.25</version>
        <!--Mysql8.0版本-->
        <!--<version>5.1.48</version>-->
        <!--Mysql5.0版本-->
    </dependency>
    
    

2. JDBC的常用API

2.1 Driver接口

  • Driver接口是所有JDBC驱动程序必须实现的接口,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指MySQL驱动JAR包)

2.2 DriverManager(驱动管理类)类

  • 用于加载JDBC驱动并且创建与数据库的连接
//向DriverManager中注册给定的JDBC驱动程序
registerDriver(Driver driver)
/*
	建立与数据库的连接,并返回表示连接的Connection对象
	url:连接路径
		jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&...
		示例:jdbc:mysql://127.0.0.1:3306/DB1
		如果连接的是本机mysql服务器且默认端口是3306,url可以简写成jdbc:mysql:///数据库名称?参数键值对1&...
		配置useSSL=false参数,禁用安全连接方式,解决警告提示
	user:用户名
	password:密码
*/
getConnection(String url, String user, String password)
  • 可用以下方法代替registerDriver注册驱动

    Class.forName("com.mysql.jdbc.Driver");
    
    //Driver的部分源码
    static{
        try{
            DriverManager.registerDriver(new Driver());
        } catch(SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    

提示:

  • Mysql 5之后的驱动包,可以省略注册驱动的步骤
  • 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类

2.3 Connection接口

  • 表示Java程序和数据库的连接,只有获得该连接对象后才能访问数据库并操作数据表
//获取表示数据库元数据的DatabaseMetaData对象
DatabaseMetaData getMetaData()
//创建一个Statement对象并将SQL语句发送到数据库
void createStatement()
//创建一个PreparedStatement对象并将参数化的SQL语句发送到数据库
void preparedStatement()
//创建一个CallableStatement对象来调用数据库存储过程
void CallableStatement()
//提交事务,并释放Connection对象当前持有的所有数据库锁,当事务被设置为手动提交时,需要调用该方法提交事务
void commit()
//回滚事务(程序出现异常时需要回滚),其它要点同上
void rollback()
//设置Connection对象的提交模式,自动:true;手动:false
void setAutoCommit(boolean autoCommit)

2.4 Statement接口

  • 执行静态的SQL语句,并返回一个结果对象
//执行各种SQL语句,返回一个boolean值,true:表示所执行的SQL语句有查询结果
boolean execute(String sql)
//执行insert\update\delete语句,返回int值,表示数据库中受该语句影响的行数
int executeUpdate(String sql)
//执行select语句,返回表示查询结果的ResultSet对象
ResultSet executeQuery(String sql)
//将sql添加到Statement对象的当前命令列表中,该方法用于SQL命令的批处理
void addBatch(String sql)
//清除Statement对象中的命令列表
void clearBatch()
//将一批sql命令提交给数据库执行,返回更新计数组成的数组
int[] executeBatch()

2.5 PreparedStatement接口

  • 执行预编译的语句,扩展了带有参数的SQL语句的执行操作使用占位符'?'代替SQL语句中的参数,然后再对其进行赋值,预防SQL注入问题

  • SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法

    //登录案例
    String name = "why";//用户名
    String pwd = " 'or'1' = '1";//密码
    String sql = "select * from users where username=' "+name+" ' and password=' "+pwd"'";
    //上述sql语句拼接后为
    select * from users where username = 'wht' and password = ''or '1' = '1';
    //无论whrer条件是否满足,后面 or '1' = '1'是始终满足的,最终条件是成立的,所以是可以正常登录的 
    //使用占位符?
    select * from users where username = 'why' and password = '\'or \'1\' = \'1'
    
    
//执行SQL语句,该语句必须是一个DML语句或者无返回内容的SQL语句,例如DDL语句
int executeUpdate()
//执行SQL查询,返回ResultSet对象
ResultSet executeQuery();
/*调用以上两个方法时不需要传递SQL语句,因为获取sql语句执行对象时已经对sql语句进行预编译了*/
//将指定参数设置为给定的X值
void setX(int parameterIndex, X x)
//将一组参数添加到此PreparedStatement对象的批处理命令中
void addBatch()
//将指定的输入流写入数据库的文本字段中
setCharacterStream(int parameterIndex, Reader reader, int length)
//将二进制的输入流写入数据库的二进制字段中
setBinaryStream(int parameterIndex, InputStream x, int length)
  • 原理

    在这里插入图片描述

    • 将sql语句发送到MySQL服务器端

    • MySQL服务端会对sql语句进行如下操作

      • 检查SQL语句

        检查SQL语句的语法是否正确。

      • 编译SQL语句。将SQL语句编译成可执行的函数。

        检查SQL和编译SQL花费的时间比执行SQL的时间还要长。如果我们只是重新设置参数,那么检查SQL语句和编译SQL语句将不需要重复执行。这样就提高了性能。

      • 执行SQL语句

2.6 ResultSet接口

  • 保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中,在ResultSet接口内部有一个指向表格数据行的游标(指针)
//获取指定字段的值,参数columnIndex代表字段的索引,columnName代表字段的名称
String getString(int columnIndex)
String getString(String columnName)
//获取指定字段的值
X getX(int columnIndex)
X getX(String columnName)
//将游标从当前位置向下移一行,新行有效返回true
boolean next()
//将游标移动到ResultSet对象的指定行
boolean absolute(int row)
//将游标移动到ResultSet对象的末尾,即最后一行之后
boolean afterlast()
//将游标移动到ResultSet对象的开头,即第一行之前
boolean beforeFirst()
//将游标从当前位置向上移一行
boolean previous()
//将游标移动到ResultSet对象的最后一行
boolean last()

3. 实现JDBC程序

//1.加载并注册数据库驱动,mysql5是com.mysql.jdbc.Driver
Class.forName("com.mysql.cj.jdbc.Driver");
//2.通过DriverManager获取数据库连接
String url = "jdbc:mysql://localhost:3306/db1?serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "select * from users";
//4.通过Connection获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//5.使用Statement对象执行sql
ResultSet rs = stmt.executeQuery(sql);
//6.操作ResultSet结果集
...
//7.关闭连接,释放资源
rs.close();
stmt.close();
conn.close();

4. 分页查询

  • 两种典型的分页方法

    • 通过ResultSet的光标实现分页

      • 通过移动的光标,可以设置记录的起始位置和结束位置来实现分页
      • 优点:在各种数据库上通用;缺点:占用大量资源,不适合数据量大的情况
    • 通过数据库机制进行分页

      select 字段列表 from 表面 limit 起始索引, 查询条目数; 
      
      • 优点:减少资源开销,提高程序性能;缺点:只针对某一种数据库通用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CL3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值