目录
1.如何通过JDBC访问数据库
2.JDBC处理事务采用什么办法
3.Class.forName 的作用
4.Statement、PreparedStatement和CallableStatement有什么区别
5.getString()方法与getObject()方法有何区别
6.使用JDBC时需要注意哪些问题
7.什么是JDO
8.JDBC和Hibernate有什么区别
1.如何通过JDBC访问数据库
JDBC用于在Java程序中实现数据库操作功能,它提供了执行SQL语句、访问各种数据库方法,并为各种不同数据库提供统一的操作接口,java.sql包中包含了JDBC操作数据库的所有类。
通过JDBC访问数据库一般有如下步骤:
1)加载JDBC驱动器。将数据库的JDBC驱动加载到classpath中,在基于JavaEE的Web应用开发中,通常把目标数据库产品的JDBC驱动复制到WEB-INF/lib下。
2)加载JDBC驱动,并将其注册到DriverManager中。一般使用反射Class.forName(String driveName)。
3)建立数据库连接,取得Connection对象。一般通过 DriverManager.getConnection(url,username,password)方法实现,url表示连接数据库的字符串,username表示连接数据库的用户名,password表示连接数据库的密码。
4)建立Statement对象或是PreparedStatement对象。
5)执行SQL语句。
6)访问结果集ResultSet对象。
7)依次将ResultSet、Statement、PreparedStatement、Connection对象关闭,释放掉所占用的资源,如rs.close(),con.close()等。这么做的原因在于JDBC驱动在底层通常都是通过网络IO实现SQL命令与数据传输的。
用JDBC访问MySQL的例子:
import java.sql.*;
public class JDBCTest {
public static void main(String[] args) throws Exception{
String user = "root";
String password = "root";
String url = "jdbc:mysql://localhost:3306/test";
String driver = "com.mysql.jdbc.Driver";
Connection con = null;
Statement stmt =null;
ResultSet rs = null;
try{
Class.forName(driver);
con = DriverManager.getConnection(url,user,password);
stmt = con.createStatement();
stmt.execute("insert into person values(1,'chs1',20)");
stmt.execute("insert into person values(2,'chs2',25)");
rs = stmt.executeQuery("select * from person");
while(rs.next()){
System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getInt(3));
}
}catch (SQLException e){
e.printStackTrace();
}finally {
try{
if(rs!=null) rs.close();
if(stmt!=null) stmt.close();
if(con!=null) con.close();
}catch (SQLException e){
System.out.println(e.getMessage());
}
}
}
}
结果:
1 chs1 20
2 chs2 25
2.JDBC处理事务采用什么办法
一个事务是由一条或多条对数据库操作的SQL语句所组成的一个不可分割的工作单元,只有当事务中的所有操作都正常执行完,整个事务才会被提交给数据库。
在JDBC中,一般通过commit()方法或rollback()方法来结束事务操作。
commit()方法表示完成对事务的提交,rollback()方法表示完成事务回滚,多用于在处理事务的过程中出现异常的情况,这两个方法都位于java.sql.Connection类中。一般而言,事务默认操作是自动提交,即操作成功后,系统自动调用commit()方法,否则调用rollback()方法。
在JDBC中,也可通过 setAutoCommit(false) 方法来禁止自动提交,然后可把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()方法来实现整体提交,如果其中一个表达式失败,就会抛出异常而不会调用commit()方法。在这种情况下,就可以在异常捕获的代码块中调用rollback()方法进行事务回滚。通过这种方法可以保持对数据库的多次操作后,数据仍然保持一致。
引申:JDBC有哪些事务隔离级别?
JDBC API支持不同类型的事务,它们由Connection对象指派或确定。在JDBC中,定义了5种事务隔离级别:
1)TRANSACTION_NONE JDB。不支持事务。
2)TRANSACTION_READ_UNCOMMITTED。未提交读。说明在提交前一个事务可以看到另一个事务的变化。这样读“脏”数据、不可重复读和虚读都是允许的。
3)TRANSACTION_READ_COMMITTED。已提交读。说明读取未提交的数据是不允许的。这个级别仍然允许不可重复读和虚读产生。
4)TRANSACTION_REPEATABLE_READ。可重复读。说明事务保证能够再次读取相同的数据而不会失败,但虚读仍会出现。
5)TRANSACTION_SERIALIZABLE。可序列化。是最高的事务级别,它防止读“脏”数据、不可重复读和虚读。
备注:
- 读“脏”数据:一个数据读取了另一个事务尚未提交的数据。
- 不可重复读:一个事务的操作导致另一个事务前后两次读取到不同的数据。
- 虚读:一个事务的操作导致另一个事务前后两次查询的结果数据量不同。
事务隔离级别越高,为避免冲突所花的精力也就越多。可以通过 Connection 对象的 conn.setTranasctionLevel() 方法来设置隔离级别,通过 conn.getTranasctionIsolation() 方法来确定当前事务的级别。
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()
举个例子:开发过程中,可把一个项目中不通用的地方抽取出来定义成一个接口BussinessInterface,针对每个公司不同的业务流程定义不同的实现类,通过创建不同的子类来完成不同公司的业务需求。为了达到良好的扩展性,可把子类采用配置文件的方式放到XML文件中。在部署时,只需从配置文件中读取类名className,然后采用 BussinessInterface b = (BussinessInterface)Class.forName(className).newInstance() 创建实例即可提高开发人员的开发效率。即使再有新的需求,开发了新的子类,也不需要需改实例代码,只需修改配置文件,使程序具有很好的可扩展性。
4.Statement、PreparedStatement和CallableStatement有什么区别
Statement | 用于执行不带参数的简单SQL语句,并返回它所生成结果的对象,每次执行SQL语句,数据库都要编译该SQL语句。 |
PreparedStatement | 表示预编译的SQL语句的对象,用于执行带参数的预编译SQL语句。 |
CallableStatement | 提供了用来调用数据库存储过程的接口,如果有输出参数要注册,说明是输出参数。 |
Statement 对象和 PreparedStatement 对象能够完成相同的功能,但相比之下,PreparedStatement 具有以下优点:
1)效率更高。使用PreparedStatement对象执行SQL命令,命令会被数据库进行编译和解析,并放到命令缓冲区,虽然会再被解析一次,但不会被再次编译,是可以重复使用的,能有效提高系统性能。因此,如果要执行插入、更新、删除等操作,最好使用PreparedStatement。鉴于此,PreparedStatement适用于存在大量用户的企业级应用软件。
2)代码可读性和可维护性更好。
3)安全性更好。使用PreparedStatement能够预防SQL注入攻击。
CallableStatement 由 prepareCall() 方法创建,它为所有DBMS(数据库管理系统)提供了一种以标准形式调用已存储过程的方法。它从PreparedStatement中继承了用于处理输入参数的方法,而且还增加了调用数据库中存储过程和函数以及设置输出类型参数的功能。
5.getString()方法与getObject()方法有何区别
JDBC提供getString()、getInt()和getData()方法从ResultSet中获取数据,当查询结果集中的数据量较小时,不用考虑性能,使用这些方法完全能够满足要求,但当查询结果集中的数据量非常大时,则会抛出异常。通常情况下,使用getObject()方法可解决。
getString()或getInt() 等方法在被调用时,程序会一次性把数据放到内存中,然后通过调用ResultSet的next()和getString()等方法获取数据。当数据量大到内存中放不下时,会抛出异常。
使用getObject()方法,数据不会一次性被读取到内存中,每次调用会直接从数据库中获取数据,不会因为数据量过大而出错。
6.使用JDBC时需要注意哪些问题
1)建立与数据库的连接,才能完成对数据库的访问。
2)及时释放不再使用的JDBC连接,只有正常关闭和释放JDBC连接,才可被快速重用,使系统性能得到改善。
3)createStatement和prepareStatement最好放在循环外面,且需要及时关闭。每次执行conn.createStatement()或conn.prepareStatement(),相当于在数据库打开了一个cursor(游标),如果放到循环内,会一直不停打开cursor。如果不及时关闭,会抛错。因此最好在执行了一次executeQuery、executeUpdate等之后,如果不需要使用ResultSet的数据,就马上将Statement关闭。
7.什么是JDO
Java数据对象(Java Data Object,JDO)是一个用于存取某种数据仓库中的对象的标准化API,它使开发人员能够间接地访问数据库。
JDO是JDBC的一个补充,它提供了透明的对象存储,存储数据对象完全不需要额外的代码,开发人员可集中时间和精力于业务逻辑上。相较JDBC,JDO更灵活、更通用,提供了到任何数据底层的存储功能,如关系数据库、文件、XML以及对象数据库管理系统等,应用可移植性更强。
8.JDBC和Hibernate有什么区别
Hibernate是JDBC的封装,采用配置文件的形式将数据库的连接参数写到XML文件中,至于对数据库的访问还是通过JDBC来完成的。
Hibernate是一个持久层框架,它将表的信息映射到XML文件中,再从XML文件映射到相应的持久化类中,这样可以使用Hibernate独特的查询语言Hibernate查询语言(HQL)了。