面试:Java 数据库操作

1. 如何通过 JDBC 访问数据库?

Java 数据库连接(Java DateBase Connectivity,即 JDBC)。

步骤:

  1. 加载JDBC驱动器。将数据库的JDBC驱动加载到 classpath中,在基于 JavaeeWeb应用开发过程中,通常要把目标数据库产品的JDBC驱动复制到WEB-INF

  2. 加载JDBC驱动,并将其注册到 DriverManager中。一般使用反射 Class.forName(String driveName)

  3. 建立数据库连接,取得 Connection对象。一般通过 DriverManager.getConnectio(url, username, passwd)方法实现,其中,url 表示连接数据库的字符串, username表示连接数据库的用户名, passwd表示连接数据库的密码

  4. 建立 Statement对象或是 PreparedStatement对象

  5. 执行SQL语句

  6. 访问结果集 Resultset对象

  7. 依次将 ResultsetStatementPreparedStatementConnection对象关闭,释放掉所占用资源,例如 rs.close()con.close()等。为什么要这么做呢?原因在于JDBC驱动在底层通常都是通过网络 IO 实现SQL命令与数据传输的。

对数据库操作的所有类都在 java.sql 里面

2. JDBC 处理事务采用什么方法?

提交:commit(),回滚:rollback(),都在 java.sql.Connection类中。一般而言事务默认操作是提交,即操作成功后系统自动调用 commit()方法,否则调用 rollback()方法。

在 JDBC 中可设置 setAutoCommit(false)来禁止自动提交,然后可以把多个数据库操作的表达式作为一个事务,成功则 commit(),一个失败抛出异常就不会提交,可以在异常捕获中 rollback()

JDBC 有哪些事务隔离级别?

事务隔离级别越高,为避免冲突所花的精力也就越多(性能也会受影响),可通过 Connection对象的 conn.setTransactionLevel()来设置隔离级别,通过 conn.setTransactionIsolation()来确定当前事务的级别。

3. Class.forName 的作用是什么?

Class.forName("com.mysql.jdbc.Driver")作用就是把这个 Mysql 的驱动器 Driver 类加载到 JVM中,同时会执行该类的静态代码段。

4. StatementPreparedStatementCallableStatement有什么区别?

Statement用于执行不带参数的简单SQL语句,并返回它所生成结果的对象,每次执行 SQL 语句时,数据库都要编译该 SQL 语句:


Statement stmt = conn.getStatement();

stmt.executeUpdate("insert into client values('aa', 'aaaa')")

PreparedStatement表示预编译的SQL语句的对象,用于执行带参数的预编译SQL语句:

Callablestatement提供了用来调用数据库中存储过程的接口,如果有输出参数要注册,说明是输出参数

虽然 Statement对象与 PreparedStatement对象能够完成相同的功能,但相比之下, PreparedStatement具有以下优点:

  1. 效率更高。在使用 PreparedStatement对象执行SQL命令时,命令会被数据库进行编译和解析,并放到命令缓冲区。然后,每当执行同一个 PreparedStatement对象时,由于在缓冲区中可以发现预编译的命令,虽然它会被再解析一次,但不会被再次编译,是可以重复使用的,能够有效提髙系统性能,因此,如果要执冇插亼、更新、删除等操作,最好使用 PreparedStatement。鉴于此, PreparedStatement适用于存在大量用户的企业级应用软件中。

  2. 代码可读性和可维护性更好。以下两种方法分别使用 StatementPreparedStatement来执行SQL语句,显然方法 2 具有更好的可读性。

  3. 安全性更好。使用 PreparedStatement能够预防SQL注入攻击,所谓SQL注入,指的是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器,达到执行恶意SQL命令的目的。注入只对SQL语句的编译过程有破坏作用,而执行阶段只是把输入串作为数据处理,不再需要对SQL语句进行解析,因此也就避免了类似 select * from user where name = ‘aa' and password='b' or 1=1’的 SQL 注入问题的发生。

CallablestatementprepareCall()方法所创建,它为所有DBMS( Database Management System,数据库管理系统)提供了一种以标准形式调用已储存过程的方法。它从 PreparedStatement继承了用于处理输入参数的方法,而且还增加了调用数据库中的存储过程和函数以及设置输出类型参数的功能。

5. getString()方法与 getObject()方法有什么区别?

getString()getInt() 等方法在被调用时,程序会一次性把数据放在内存中,然后通过调用 ResultSetnext()getString()等方法来获取数据,当数据量大到内存放不时,就会抛出异常,而使getObject()就不会有这种问题,因为数据不会一次性读到内存中,而是每次调用时都直接从数据库中去获取数据。

6. 使用 JDBC 时需要注意那些问题?

在使用JDBC编程时,首先需要建立于数据库的连接,才能完成对数据库的访问,由于与数据库的连接是非常重要的资源。JDBC连接池提供了JDBC连接定义和数目有限的连接,如果连接数量不够,就需要长时间的等待。不正常关闭JDBC连接会导致等待回收无效的JDBC连接。只有正常的关闭和释放JDBC连接,JDBC资源才可以被快速地重用,从而使得系统性能得到改善。因此在编程时,一定要保证释放不再使用的连接。

一般来讲,在使用JDBC访问数据库时, createStatementprepareStatement最好放在循环外面,而且使用了这些 Statement后,需要及时关闭。最好是在执行了一次executeQueryexecuteUpdate等之后,如果不需要使用结果集( Resultset)的数据,就马上将 Statement关闭。因为每次执行 conn.create Statement()conn.prepareStatement(),实际上都相当于在数据库中打开了一个 cursor(游标),如果把对这两个方法的调用放到循环内,会一直不停地打开 cursor如果不能及时地关闭,会导致程序抛出异常。

7. 什么是 JDO

Java数据对象( Java Data Object,JDO)是一个用于存取某种数据仓库中的对象的标准化API,它使开发人员能够间接地访问数据库。

JDOJDBC的一个补充,它提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(例如 JDBC API的使用)。这些烦琐的工作已经转移到JDO产品提供商身上,使开发人员解脱岀来,从而集中时间和精力在业务逻辑上。另外,相较于JDBCJDO更灵活、更通用,它提供了到任何数据底层的存储功能,例如关系数据库、文件、ⅩML以及对象数据库管理系统( Object Database Management System, ODBMS)等,使得应用可移植性更强。

8. JDBC 与 Hibernate 的区别

HibernateJDBC的封装,采用配置文件的形式将数据库的连接参数写到XML文件中,至于对数据库的访问还是通过JDBC来完成的。

Hibernate是一个持久层框架,它将表的信息映射到 XML 文件中,再从 XML 文件映射到相应的持久化类中,这样可以使用 Hibernate独特的查询语言 Hibernate查询语言( Hibernate Query Language,HQL )了。Hibernate 的HQL查询语句返回的List<Object[.]>类,而JDBC通过 statement返回的查询结果是 ResultSet并且有时候需要自己封装到List中。另外一个重要区别在于, Hibernate具有访问层(DAO类层,DAO全称为 Data Access Object 数据访问接口,意为数据访问接口),该层是HQL 查询语句唯一出现的位置,再往上层则不会出现查询语句,而JDBC可以随时连接随时访问,例如有100个类都有SQL查询语句,如果表名改变了,那么要使用JDBC的方式,就必须重写所有查询语句,而采用 Hibernate的方式只需修改DAO层的类即可,因此 Hibernate具有很好的维护性和扩展性。