java程序员面试笔试宝典4.11 Java数据库操作

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

Java数据库连接(JDBC)用于再java程序中实现数据库操作功能,它提供了执行SQL语句,访问各种数据库的方法,并为各种不同的数据库提供统一的操作接口。
java.sql包中包含了JDBC操作数据库的所有类,通过jdbc访问数据库一般有如下几个步骤:
1)加载JDBC驱动器。
将数据库的JDBC驱动器加载到classpath中,在基于JavaEE的Web应用开发过程中,通常要把目标数据库产品的JDBC驱动复制到WEB-INF/lib下。
2)加载JDBC驱动,并将其注册到DriverManager中。一般使用反射Class.forName(String driverName)
3)建立数据库连接,取得Connection对象,一般通过DriverManager.getConnection(url,username,password)方法实现
4)建立Statement对象或是PreparedStatement对象。
5)执行SQL语句。
6)访问结果集ResultSet对象
7)依次将ResultSet,Statement,PreparedStatement,Connection对象关闭,释放掉所占用的资源。
例如rs.close(),con.close()等
因为JDBC驱动在底层通常是通过网络IO实现SQL命令与数据传输的。
1:举出一个用JDBC访问MySQL的例子
package com.zcl.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Test {
    public static void main(String[] args) {
        String user = "user1";
        String password = "password1";
        String url = "jdbc:mysql://localhost:3306/Test";
        String driver = "com.mysql.jdbc.Driver";
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, user, password);
            stat = conn.createStatement();
            stat.execute("insert into Employee values(1,'zhangsan',23)");
            stat.execute("insert into Employee values(2,'lisi',25)");
            rs = stat.executeQuery("select * from Employee");
            while(rs.next()){
                System.out.println(rs.getInt(1)+" "+rs.getInt(2)+" "+rs.getInt(3));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                if(rs!=null){
                    rs.close();
                }
                if(stat!=null){
                    stat.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }
}

程序运行结果:
1 zhangsan 23
2 lisi 25

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

一个事务是由一条或多条对数据库的操作的sql语句所组成的一个不可分割的工作单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库。
在jdbc中,一般是通过commit()方法或者rollback()方法来结束事务的操作
commit()方法表示完成对事务的提交
rollback()方法表示完成事务回滚,多用于在处理事务的过程中出现异常的情况。
这两种方法都位于java.sql.Connection类中
一般而言,事务默认操作是自动提交,即操作成功后,系统将自动调用commit()方法,否则将调用rollbak()方法。

在jdbc中,也可以通过调用setAutoCommit(false)方法来禁止自动提交,然后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()方法实现整体提交。
如果其中一个表达式操作失败,就会抛出异常而不会调用commmit()方法。
在这种情况下就可以在异常捕获的代码块中调用rollback()方法进行事务回滚。通过此方法可以保持对数据库的多次操作后,数据仍然保持一致性。


引申:jdbc有哪些事务隔离级别?
为了解决“多个线程请求相同数据”相关的问题,事务之间通常会用锁相互隔离开。
在jdbc中,定义了以下5种事务隔离级别:
1)TRANSACTION_NONE JDB.不支持事务
2)TRANSACTION_READ_UNCOMMITTED.未提交读。说明在提交前一个事务可以看到另一个事务的变化。这样读脏数据,不可重复读和虚读都是允许的。
3)TRANSACTION_READ_COMMITTED.已提交读。说明读取未提交的数据是不允许的,这个级别仍然允许不可重复读和虚读产生。
4)TRANSACTIONN_REPEATABLE_READ.可重复读,说明事务保证能够再次读取相同的数据而不会失败,但是虚读仍然会出现。
5)TRANSACTION_SERIALIZABLE.可序列化。是最高的事务级别,它防止读脏数据,不可重复读和虚读。

脏数据:一个事务读取了另一个事务尚未提交的数据。
不可重复读:一个事务的操作导致另一个事务前后两次读取到不同的数据。
虚读:一个事务的操作导致另一个事务前后两次查询的结果数据量不同。

事务隔离级别越高,为避免冲突所花的精力也越多,可以通过Connection对象的conn.setTransactionLevel()方法来设置隔离级别,
通过conn.getTransactionIsolation()方法来确定当前事务的级别。

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

在java语言种,任何类只有被装载到JVM上才能运行,Class.forName()方法的作用就是把类加载到JVM中。
它会返回一个与带有给定字符串名的类或接口相关联的Class对象,并且JVM会加载这个类,同时JVM会执行该类的静态代码段。
在使用JDBC连接数据库时,一般都会调用Class.forName("com.mysql.jdbc.Driver")方法来加载JDBC驱动,那么是否一定需要调用这个方法呢?为什么?
并不是一定要调用这个方法
例如:
Test t = (Test)Class.forName("Test").newInstance()语句和
Test t = new Test()
具有相同的效果
区别:创建对象的方式不同,
前者使用类加载机制,提高软件的可扩展性。
后者创建了一个新的类

JDBC规范中要求Driver类在使用前必须想DriverManager注册自己,所以,当执行Class.forName("com.mysql.jdbc.Driver")时,
JVM会加载名字为“com.mysql.jdbc.Driver”对应的Driver类,而com.mysql.jdbc.Driver类的实现如下所示:
public class Driver extends NonRegisteringDriver implements Java.sql.Driver{
    static{
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException e) {
            throw new RuntimeException("Cant't register driver");
        }
    }
在调用Class.forName()方法时,这个Driver类被加载了,
由于静态部分被执行,因此Driver也被注册到了DriverManager中。

4.Statement,PreparedStatement和CallableStatement有什么区别?

Statement用于执行不带参数的简单的SQL语句,并返回它所生成的结果的对象。每次执行sql语句时,数据库都要编译该sql语句。
以下是一个最简单的sql语句。
Statement stat = conn.createStatement();
stat.execute("insert into Employee values(1,'zhangsan',23)");
PrepareStatement表示预编译的SQL语句的对象,用于执行带参数的预编译的sql语句。
CallableStatement则提供了用来调用数据库中存储过程的接口,如果有输出参数要注册,说明是输出参数。
例:PreparedStatement的例子
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test {
    public static void main(String[] args) {
        String user = "user1";
        String password = "password1";
        String url = "jdbc:mysql://localhost:3306/Test";
        String driver = "com.mysql.jdbc.Driver";
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, user, password);
            ps = conn.prepareStatement("select * from Employee where id=?");
            ps.setInt(1, 1);//传递参数(第一个问号,传递的值)
            rs = ps.executeQuery();
            while(rs.next()){
                System.out.println(rs.getInt(1)+" "+rs.getInt(2)+" "+rs.getInt(3));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                if(rs!=null){
                    rs.close();
                }
                if(ps!=null){
                    ps.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }
}

结果:
1 zhangsan 23
虽然Statement对象与PreparedStatement对象能完成相同的功能,但是相比之下,PreparedStatement具有以下优点:
1)效率 更高
2)代码的可读性和可维护性更好。
3)安全性更好,能够预防SQL注入攻击
select * from user where name='aa' and password='bb' or 1=1

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

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

JDBC提供了getString(),getInt(),和getDate()等方法从ResultSet中获取数据。
getString和getInt等方法在被调用时,程序会一次性把数据都放到内存中,然后通过调用ResultSet的next和getString等方法来获取数据。
当数据量太大到内存中放不下就会报异常。
getObject()每次调用会直接去数据库中获取数据,不会因为数据量太大抛出异常。

6.使用JDBC需要注意什么?

一定要释放不再使用的连接。
createStetement和prepareStatement最好放在循环外面,并且需要及时关闭。

7.什么是JDO

java数据对象是一个用于存取某种数据仓库中的对象的标准化API,它使开发人员能够间接地访问数据库。
JDO是JDBC的一个补存,提供了透明的对象存储。

8.JDBC与Hibernate有什么区别?

Hibernate是JDBC的封装,采用配置文件的形式将数据库的连接参数写到xml文件中,至于对数据库的访问还是通过JDBC来完成的。
Hibernate是一个持久层框架,它将表的信息映射到XML文件中,再从XML文件映射到相应的持久化类中,这样就可以使用Hibernate独特的查询语言hql了。
1)Hibernate的HQL查询语言返回的是List<Object[.]>类
JDBC返回的是ResultSet并且有时候需要自己封装到List中。
2)Hibernate具有访问层,dao层类,具有很好的维护性和扩展性。

猜你喜欢

转载自blog.csdn.net/m0_37301141/article/details/80497877
今日推荐