JDBC⾯试题
JDBC常见⾯试题集锦
⼀、概念
1.什么是JDBC,在什么时候会⽤到它?
JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以⽤它来操作关系型数据库。JDBC接⼝及相关类在java.sql包和javax.sql包⾥。我们可以⽤它来连接数据库,执⾏SQL查询,存储过程,并处理返回的结果。JDBC接⼝让Java程序和JDBC 驱动实现了松耦合,使得切换不同的数据库变得更加简单。
2.有哪些不同类型的JDBC驱动?
有四类JDBC驱动。和数据库进⾏交互的Java程序分成两个部分,⼀部分是JDBC的API,实际⼯作的驱动则是另⼀部分。(1)JDBC-ODBC Bridge plus ODBC Driver(类型1):它使⽤ODBC驱动连接数据库。需要安装ODBC以便连接数据库,正因为这样,这种⽅式现在已经基本淘汰了。(2)Native API partly Java technology-enabled driver(类型2):这种驱动把JDBC调⽤适配成数据库的本地接⼝的调⽤。(3)Pure Java Driver for Database Middleware(类型3):这个驱动把JDBC 调⽤转发
给中间件服务器,由它去和不同的数据库进⾏连接。⽤这种类型的驱动需要部署中间件服务器。这种⽅式增加了额外的⽹络调⽤,导致性能变差,因此很少使⽤。(4)Direct-to-Database Pure Java Driver(类型4):这个驱动把JDBC转化成数据库使⽤的⽹络协议。这种⽅案最简单,也适合通过⽹络连接数据库。不过使⽤这种⽅式的话,需要根据不同数据库选⽤特定的驱动程序,⽐如OJDBC是Oracle 开发的Oracle数据库的驱动,⽽MySQL Connector/J是MySQL数据库的驱动。
3.JDBC是如何实现Java程序和JDBC驱动的松耦合的?
JDBC API使⽤Java的反射机制来实现Java程序和JDBC驱动的松耦合。随便看⼀个简单的JDBC⽰例,你会发现所有操作都是通过JDBC接⼝完成的,⽽驱动只有在通过Class.forName反射机制来加载的时候才会出现。
4.什么是JDBC连接,在Java中如何创建⼀个JDBC连接?
JDBC连接是和数据库服务器建⽴的⼀个会话。你可以想像成是⼀个和数据库的Socket连接。创建JDBC连接很简单,只需要两步:
A. 注册并加载驱动:使⽤Class.forName(),驱动类就会注册到DriverManager⾥⾯并加载到内存⾥。
B. ⽤DriverManager获取连接对象:调⽤Connnection()⽅法并传⼊数据库连接的U
RL,⽤户名及密码,就能获取到连接对象。
Connection con = null;
try{
// load the Driver Class
Class.forName("sql.jdbc.Driver");
// create the connection now
con = Connection("jdbc:mysql://localhost:3306/UserDB",
"pankaj",
"pankaj123");
}catch (SQLException e) {
System.out.println("Check database is UP and configs are correct");
e.printStackTrace();
}catch (ClassNotFoundException e) {
System.out.println("Please include JDBC MySQL jar in classpath");
e.printStackTrace();
}
5.JDBC的DriverManager是⽤来做什么的?
JDBC的DriverManager是⼀个⼯⼚类,我们通过它来创建数据库连接。当JDBC的Driver 类被加载进来时,它会⾃⼰注册到DriverManager类⾥⾯,你可以看下JDBC Driver类的源码来了解⼀下。然后我们会把数据库配置信息传成Connection()⽅法,DriverManager会使⽤注册到它⾥⾯的驱动来获取数据库连接,并返回给调⽤的程序。office2019激活后没有access
6.在Java程序中,如何获取数据库服务器的相关信息?
使⽤DatabaseMetaData可以获取到服务器的信息。当和数据库的连接成功建⽴了之后,可以通过调⽤
getMetaData()⽅法来获取数据库的元信息。DatabaseMetaData⾥⾯有很多⽅法,通过它们可以获取到数据库的产品名称,版本号,配置信息等。
DatabaseMetaDatametaData = MetaData();
String dbProduct = DatabaseProductName();
7.JDBC的Statement是什么?
Statement是JDBC中⽤来执⾏数据库SQL查询语句的接⼝。通过调⽤连接对象的getStatement()⽅法我们可以⽣成⼀个Statement对象。我们可以通过调⽤它的execute(),executeQuery(),executeUpdate()⽅法来执⾏静态SQL查询。
由于SQL语句是程序中传⼊的,如果没有对⽤户输⼊进⾏校验的话可能会引起SQL注⼊的问题,如果想了解更多关于SQL注⼊的,可以看下这⾥。默认情况下,⼀个Statement同时只能打开⼀个ResultSet。如果想操作多个ResultSet对象的话,需要创建多个Statement。
Statement接⼝的所有execute⽅法开始执⾏时都默认会关闭当前打开的ResultSet。
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⽅法。
7.JDBC的PreparedStatement是什么?
PreparedStatement对象代表的是⼀个预编译的SQL语句。⽤它提供的setter⽅法可以传⼊查询的变量。由于PreparedStatement是预编译的,通过它可以将对应的SQL语句⾼效的执⾏多次。由于PreparedStatement⾃动对特殊字符转义,避免了SQL注⼊攻击,因此应当尽量的使⽤它。PreparedStatement中如何注⼊NULL值?
可以使⽤它的setNull⽅法来把null值绑定到指定的变量上。setNull⽅法需要传⼊参数的索引以及SQL字段的类型,像这样:
ps.setNull(10, java.sql.Types.INTEGER);.
Statement中的getGeneratedKeys⽅法有什么⽤?
有的时候表会⽣成主键,这时候就可以⽤Statement的getGeneratedKeys()⽅法来获取这个⾃动⽣成的主键的值了。相对于Statement,PreparedStatement的优点是什么?
它和Statement相⽐优点在于:PreparedStatement有助于防⽌SQL注⼊,因为它会⾃动对特殊字符转义。PreparedStatement 可以⽤来进⾏动态查询。PreparedStatement执⾏更快。尤其当你重⽤它或者使⽤它的拼量查询接⼝执⾏多条语句时。使⽤PreparedStatement的setter⽅法更容易写出⾯向对象的代码,⽽Statement的话,我们得拼接字符串来⽣成查询语句。如果参数太多了,字符串拼接看起来会⾮常丑陋并且容易出错。
8.PreparedStatement的缺点是什么,怎么解决这个问题?
PreparedStatement的⼀个缺点是,我们不能直接⽤它来执⾏in条件语句;需要执⾏
IN条件语句的话,下⾯有⼀些解决⽅案:分别进⾏单条查询——这样做性能很差,不推荐。使⽤存储过程——这取决于数据库的实现,不是所有数据库都⽀持。动态⽣成PreparedStatement——这是个好办法,但是不能享受PreparedStatement的缓存带来的好处了。在PreparedStatement查询中使⽤NULL值——如果你知道输⼊变量的最⼤个数的话,这是个不错的办法,扩
展⼀下还可以⽀持⽆限参数。
关于这个问题更详细的分析可以看下这篇⽂章。
9.JDBC的ResultSet是什么?
在查询数据库后会返回⼀个ResultSet,它就像是查询结果集的⼀张数据表。ResultSet对象维护了⼀个游标,指向当前的数据⾏。开始的时候这个游标指向的是第⼀⾏。如果调⽤了ResultSet的next()⽅法游标会下移⼀⾏,如果没有更多的数据
了,next()⽅法会返回false。可以在for循环中⽤它来遍历数据集。默认的ResultSet是不能更新的,游
标也只能往下移。也就是说你只能从第⼀⾏到最后⼀⾏遍历⼀遍。不过也可以创建可以回滚或者可更新的ResultSet,像下⾯这样。
Statement stmt = ateStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
当⽣成ResultSet的Statement对象要关闭或者重新执⾏或是获取下⼀个ResultSet的时候,ResultSet对象也会⾃动关闭。可以通过ResultSet的getter⽅法,传⼊列名或者从1开始的序号来获取列数据。
10.有哪些不同的ResultSet?
根据创建Statement时输⼊参数的不同,会对应不同类型的ResultSet。如果你看下Connection的⽅法,你会发现createStatement和prepareStatement⽅法重载了,以⽀持不同的ResultSet和并发类型。⼀共有三种ResultSet对象。ResultSet.TYPE_FORWARD_ONLY:这是默认的类型,它的游标只能往下移。
ResultSet.TYPE_SCROLL_INSENSITIVE:游标可以上下移动,⼀旦它创建后,数据库⾥的数据再发⽣修改,对它来说是透明的。
ResultSet.TYPE_SCROLL_SENSITIVE:游标可以上下移动,如果⽣成后数据库还发⽣了修改操作,
它是能够感知到的。
11.ResultSet有两种并发类型。
ResultSet.CONCUR_READ_ONLY:ResultSet是只读的,这是默认类型。
ResultSet.CONCUR_UPDATABLE:我们可以使⽤ResultSet的更新⽅法来更新⾥⾯的数据。
12.Statement中的setFetchSize和setMaxRows⽅法有什么⽤处?
setMaxRows可以⽤来限制返回的数据集的⾏数。当然通过SQL语句也可以实现这个功能。⽐如在MySQL中我们可以⽤LIMIT 条件来设置返回结果的最⼤⾏数。
setFetchSize理解起来就有点费劲了,因为你得知道Statement和ResultSet是怎么⼯作的。当数据库在执⾏⼀条查询语句时,查询到的数据是在数据库的缓存中维护的。ResultSet 其实引⽤的是数据库中缓存的结果。
假设我们有⼀条查询返回了100⾏数据,我们把fetchSize设置成了10,那么数据库驱动每次只会取10条数据,也就是说得取10次。当每条数据需要处理的时间⽐较长的时候并且返回数据⼜⾮常多的时候,这个可选的参数就变得⾮常有⽤了。我们可以通过Statement 来设置fetchSize参数,不过它会被ResultSet对象设置进来的值所覆盖掉。
13.如何使⽤JDBC接⼝来调⽤存储过程?
存储过程就是数据库编译好的⼀组SQL语句,可以通过JDBC接⼝来进⾏调⽤。我们可以通过JDBC的CallableStatement接⼝来在数据库中执⾏存储过程。初始化CallableStatement 的语法是这样的:
CallableStatementstmt = con.prepareCall("{call insertEmployee(?,?,?,?,?,?)}"); stmt.setInt(1, id);
stmt.setString(2, name);
stmt.setString(3, role);
stmt.setString(4, city);
stmt.setString(5, country);
//register the OUT parameter before calling the stored procedure
我们得在执⾏CallableStatement之前注册OUT参数。关于这个更详细的资料可以看这⾥。
13.JDBC的批处理是什么,有什么好处?
有时候类似的查询我们需要执⾏很多遍,⽐如从CSV⽂件中加载数据到关系型数据库的表⾥。我们也知道,执⾏查询可以⽤Statement或者PreparedStatement。除此之外,JDBC还提供了批处理的特性,有了它,我们可以在⼀次数据库调⽤中执⾏多条查询语句。JDBC通过Statement和PreparedStatement中的addBatch和executeBatch⽅法来⽀持批处理。批处理⽐⼀条条语句执⾏的速度要快得多,因为它需要很少的数据库调⽤,想进⼀步了解请点这⾥。
14.JDBC的事务管理是什么,为什么需要它?
默认情况下,我们创建的数据库连接,是⼯作在⾃动提交的模式下的。这意味着只要我们执⾏完⼀条查询语句,就会⾃动进⾏提交。因此我们的每条查询,实际上都是⼀个事务,如果我们执⾏的是DML或者DDL,每条语句完成的时候,数据库就已经完成修改了。
有的时候我们希望由⼀组SQL查询组成⼀个事务,如果它们都执⾏OK我们再进⾏提交,如果中途出现异常了,我们可以进⾏回滚。
JDBC接⼝提供了⼀个setAutoCommit(boolean flag)⽅法,我们可以⽤它来关闭连接⾃动提交的特性。我们应该在需要⼿动提交时才关闭这个特性,不然的话事务不会⾃动提交,每次都得⼿动提交。数据
库通过表锁来管理事务,这个操作⾮常消耗资源。因此我们应当完成操作后尽快的提交事务。在这⾥有更多关于事务的⽰例程序。
15.如何回滚事务?
通过Connection对象的rollback⽅法可以回滚事务。它会回滚这次事务中的所有修改操作,并释放当前连接所持有的数据库锁。
16.JDBC的保存点(Savepoint)是什么,如何使⽤?
有时候事务包含了⼀组语句,⽽我们希望回滚到这个事务的某个特定的点。JDBC的保存点可以⽤来⽣成事务的⼀个检查点,使得事务可以回滚到这个检查点。
⼀旦事务提交或者回滚了,它⽣成的任何保存点都会⾃动释放并失效。回滚事务到某个特定的保存点后,这个保存点后所有其它的保存点会⾃动释放并且失效。可以读下这个了解更多关于JDBC Savepoint的信息。
17.JDBC的DataSource是什么,有什么好处?
DataSource即数据源,它是定义在javax.sql中的⼀个接⼝,跟DriverManager相⽐,它的功能要更强
⼤。我们可以⽤它来创建数据库连接,当然驱动的实现类会实际去完成这个⼯作。除了能创建连接外,它还提供了如下的特性:
1.缓存PreparedStatement以便更快的执⾏
2.可以设置连接超时时间
3.提供⽇志记录的功能
4.ResultSet⼤⼩的最⼤阈值设置
通过JNDI的⽀持,可以为servlet容器提供连接池的功能
18.如何通过JDBC的DataSource和Apache Tomcat的JNDI 来创建连接池?
对部署在servlet容器中的WEB程序⽽⾔,创建数据库连接池⾮常简单,仅需要以下⼏步。在容器的配置⽂件中创建JDBC的JNDI资源,通常在l或者l⾥⾯。像这样:
global="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="sql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/UserDB"
username="pankaj"
哈工大不能用matlab为什么password="pankaj123"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
mysql面试题基础global="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource" />
在WEB应⽤程序中,先⽤InitialContext来查JNDI资源,然后获取连接。
Context ctx = new InitialContext();googlechromebrowser
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
19.Apache的DBCP是什么?
如果⽤DataSource来获取连接的话,通常获取连接的代码和驱动特定的DataSource 是紧耦合的。另外,除了选择DataSource的实现类,剩下的代码基本都是⼀样的。
Apache的DBCP就是⽤来解决这些问题的,它提供的DataSource实现成为了应⽤程序和不同JDBC驱动间的⼀个抽象层。Apache的DBCP库依赖commons-pool库,所以要确保它们都在部署路径下。
20.什么是数据库的隔离级别?
当我们为了数据的⼀致性使⽤事务时,数据库系统⽤锁来防⽌别⼈访问事务中⽤到的数据。数据库通过锁来防⽌脏读,不可重复读(Non-Repeatable Reads)及幻读(Phantom-Read)的问题。
数据库使⽤JDBC设置的隔离级别来决定它使⽤何种锁机制,我们可以通过Connection 的getTransactionIsolation和setTransactionIsolation⽅法来获取和设置数据库的隔离
级别。
隔离级别事务脏读不可重复读幻读
TRANSACTION_NONE 不⽀持不可⽤不可⽤不可⽤
TRANSACTION_READ_COMMITTED ⽀持阻⽌允许允许
TRANSACTION_READ_UNCOMMITTED ⽀持允许允许允许
TRANSACTION_REPEATABLE_READ ⽀持阻⽌阻⽌允许
TRANSACTION_SERIALIZABLE ⽀持阻⽌阻⽌阻⽌
21.JDBC的RowSet是什么,有哪些不同的RowSet?
二郎腿跷多了怎么矫正RowSet⽤于存储查询的数据结果,和ResultSet相⽐,它更具灵活性。RowSet继承⾃ResultSet,因此ResultSet能⼲的,它们也能,⽽ResultSet做不到的,它们还是可以。RowSet接⼝定义在javax.sql包
combopooleddatasource⾥。
22.RowSet提供的额外的特性有:
提供了Java Bean的功能,可以通过settter和getter⽅法来设置和获取属性。RowSet使⽤了JavaBean的事件驱动模型,它可以给注册的组件发送事件通知,⽐如游标的移动,⾏的增删改,以及RowSet内容的修改等。
RowSet对象默认是可滚动,可更新的,因此如果数据库系统不⽀持ResultSet实现类似的功能,可以使⽤RowSet来实现。RowSet分为两⼤类:
A. 连接型RowSet——这类对象与数据库进⾏连接,和ResultSet很类似。JDBC接⼝只提供了⼀种连接型
RowSet,wset.JdbcRowSet,它的标准实现是wset.JdbcRowSetImpl。
B. 离线型RowSet——这类对象不需要和数据库进⾏连接,因此它们更轻量级,更容易序列化。它们适⽤于在⽹络间传递数据。有四种不同的离线型RowSet的实现。
CachedRowSet——可以通过他们获取连接,执⾏查询并读取ResultSet的数据到RowSet⾥。我们可以在离线时对数据进⾏维
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论