• JDBC 面试题


    什么是JDBC,什么时候用的到它

    JDBC的全程是 Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库。JDBC接口及相关类在java.sql包和javax.sql包里。我们可以用它来连接数据库,执行SQL查询,存储过程,并处理返回的结果。

    JDBC接口让Java程序和JDBC驱动实现了减耦合,使得切换不同的数据库变得简单。

    有哪些不同的类型的JDBC驱动?

    有四类JDBC驱动,和数据库进行交互的java程序分成两个部分,一部分是JDBC的API,实际工作的驱动则是另一部分。

    A JDC-ODBC Bridge plus ODBC Driver:它使用ODBC驱动连接数据库。需要安装ODBC以便连接数据库,正因为这样,这种方式现在已经基本淘汰了。
    B Native API partly Java technology-enabled driver:这种驱动把JDBC调用适配成数据库的本地接口的调用。
    C Pure Java Driver for Database Middleware:这个驱动把JDBC调用转发给中间件服务器,由它去和不同的数据库进行连接。用这种类型的驱动需要部署中间件服务器。这种方式增加了额外的网络调用,导致性能变差,因此很少使用。
    D Direct-to-Database Pure Java Driver:这个驱动把JDBC转化成数据库使用的网络协议。这种方案最简单,也适合通过网络连接数据库。不过使用这种方式的话,需要根据不同数据库选用特定的驱动程序,比如OJDBC是Oracle开发的Oracle数据库的驱动,而MySQL Connector/J是MySQL数据库的驱动。

    JDBC是如何实现Java程序和JDBC驱动的松耦合

    JDBC API使用Java的反射机制来实现Java程序和JDBC驱动的松耦合。随便看一个简单的JDBC示例,你会发现所有操作都是通过JDBC接口完成的,而驱动只有在通过Class.forName反射机制来加载的时候才会出现。
    这是Java核心库里反射机制的最佳实践之一,它使得应用程序和驱动程序之间进行了隔离,让迁移数据库的工作变得更简单。

    什么是JDBC连接,在Java中如何创建一个JDBC连接?

    建立jdbc连接过程如下:

    1、注册数据库驱动

    2、建立数据库连接

    3、创建一个Statement

    4、执行SQL语句

    5、处理结果集

    6、关闭数据库连接

    
    
    package com.xyfer;
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
     
    public class JdbcTest {
     
    	public static void main(String[] args) {
    		
    		Connection connection = null;
    		PreparedStatement preparedStatement = null;
    		ResultSet resultSet = null;
    		
    		try {
    			//加载数据库驱动
    			Class.forName("com.mysql.jdbc.Driver");
    			
    			//通过驱动管理类获取数据库链接
    			connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
    			//定义sql语句 ?表示占位符
    			String sql = "select * from user where username = ?";
    			//获取预处理statement
    			preparedStatement = connection.prepareStatement(sql);
    			//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
    			preparedStatement.setString(1, "小黑");
    			//向数据库发出sql执行查询,查询出结果集
    			resultSet =  preparedStatement.executeQuery();
    			//遍历查询结果集
    			while(resultSet.next()){
    				System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			//释放资源
    			if(resultSet!=null){
    				try {
    					resultSet.close();
    				} catch (SQLException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			if(preparedStatement!=null){
    				try {
    					preparedStatement.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();
    				}
    			}
    		}
    	}
     
    }
    
    

    JDBC中的 Statement、PreparedStatement 和 CallableStatement的区别?

    区别:

    • PreparedStatement是预编译的SQL语句,效率高于Statement。

    • PreparedStatement支持?操作符,相对于Statement更加灵活。

    • PreparedStatement可以防止SQL注入,安全性高于Statement。

    • CallableStatement适用于执行存储过程。

    JDBC中大数据量的分页解决方法?

    最好的方法就是利用sql语句进行分页,这样每次查询出的结果集中就只包含某页的数据内容

    mysql语法:

    
        SELECT * FROM 表名 LIMIT [START], length;
        
    

    oracle语法:

        SELECT *FROM (
            SELECT 列名,列名,ROWNUM rn
            FROM 表名
            WHERE ROWNUM<=(currentPage*lineSize)) temp
        
        WHERE temp.rn>(currentPage-1)*lineSize;
    

    数据库连接池工作原理和实现方案?

    工作原理:

    • JAVA EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。

    实现方案:

    • **连接池使用集合来进行装载,返回的Connection是原始Connection的代理,代理Connection的close方法,当调用close方法时,不是真正关连接,而是把它代理的Connection对象放回到连接池中,等待下一次重复利用。
      **

    Java中如何进行事务的处理?

    1.事务是作为单个逻辑工作单元执行的一系列操作。
    2.一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务

    Connection类中提供了4个事务处理方法:

    • setAutoCommit(Boolean autoCommit):设置是否自动提交事务,默认为自动提交,即为true,通过设置false禁止自动提交事务

    • commit():提交事务

    • rollback():回滚事务

    • savepoint:保存点

      • 注意:savepoint不会结束当前事务,普通提交和回滚都会结束当前事务的

    JDBC是如何实现Java程序和JDBC驱动的松耦合的?

    通过制定接口,数据库厂商来实现。我们只要通过接口调用即可。随便看一个简单的JDBC示例,你会发现所有操作都是通过JDBC接口完成的,而驱动只有在通过Class.forName反射机制来加载的时候才会出现。

    execute,executeQuery,executeUpdate的区别是什么?

    • Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpdateCount()方法来获取更新的记录条数。

    • Statement的executeQuery(String query)接口用来执行select查询,并且返回ResultSet。即使查询不到记录返回的ResultSet也不会为null。我们通常使用executeQuery来执行查询语句,这样的话如果传进来的是insert或者update语句的话,它会抛出错误信息为 “executeQuery method can not be used for update”的java.util.SQLException。

    • Statement的executeUpdate(String query)方法用来执行insert或者update/delete(DML)语句,或者 什么也不返回DDL语句。返回值是int类型,如果是DML语句的话,它就是更新的条数,如果是DDL的话,就返回0。

    • 只有当你不确定是什么语句的时候才应该使用execute()方法,否则应该使用executeQuery或者executeUpdate方法。

    JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?

    脏读:一个事务读取到另外一个事务未提交的数据

    例子:A向B转账,A执行了转账语句,但A还没有提交事务,B读取数据,发现自己账户钱变多了!B跟A说,我已经收到钱了。A回滚事务【rollback】,等B再查看账户的钱时,发现钱并没有多。

    下面的三种个隔离级别都可以防止:

    • Serializable【TRANSACTION_SERIALIZABLE】

    • Repeatable read【TRANSACTION_REPEATABLE_READ】

    • Read committed【TRANSACTION_READ_COMMITTED】

    什么是幻读,哪种隔离级别可以防止幻读?

    是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

    只有TRANSACTION_SERIALIZABLE隔离级别才能防止产生幻读。

    JDBC的DriverManager是用来做什么的?

    • JDBC的DriverManager是一个工厂类,我们通过它来创建数据库连接。

    • 当JDBC的Driver类被加载进来时,它会自己注册到DriverManager类里面

    • 然后我们会把数据库配置信息传成DriverManager.getConnection()方法,DriverManager会使用注册到它里面的驱动来获取数据库连接,并返回给调用的程序。

    JDBC的ResultSet是什么?

    • 在查询数据库后会返回一个ResultSet,它就像是查询结果集的一张数据表。

    • ResultSet对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了ResultSet的next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回false。可以在for循环中用它来遍历数据集。

    • 默认的ResultSet是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的ResultSet

    • 当生成ResultSet的Statement对象要关闭或者重新执行或是获取下一个ResultSet的时候,ResultSet对象也会自动关闭。

    • 可以通过ResultSet的getter方法,传入列名或者从1开始的序号来获取列数据。

  • 相关阅读:
    python并发编程之深入理解yield from
    python中的多进程编程
    Python并发concurrent、Future类、异步
    【Socket通信】关于Socket通信原理解析及python实现
    深入理解Python元类
    Django RestFrameWork 源码解析
    Django的Restful规范
    小程序colorUI框架初步使用教程
    类似按键精灵的鼠标键盘录制和自动化操作 模拟点击和键入 (KeyMouseGo)
    如何在postgresql中,一句sql完成未有数据记录的insert,再update的操作
  • 原文地址:https://www.cnblogs.com/nineberg/p/12286869.html
Copyright © 2020-2023  润新知