jdbc的相关知识
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdbc的相关知识相关的知识,希望对你有一定的参考价值。
如何通过jdbc访问数据库?
java数据库连接(java Database Connectivity,jdbc)是一种用于实现java程序中数据库操作功能。它提供了执行sql语句,访问各种数据库的方法,并为个各种不同的数据库提供了相同的操作接口。java.sql中包含了所有数据库操作的类。通过jdbc操作数据库主要有以下几步:
(1)加载驱动器,将数据库的驱动加载到classpath中,在基于javaee的web开发中,一般将数据库驱动拷贝到WEB—INF/lib下。
(2)加载驱动,将数据库驱动注册到Drivermanager中,通过反射class.forname(String drivename)。
(3)创建数据库连接,获得connection对象,一般使用DriverManager.getConnection(url,username,passwd)。其中url是连接数据库的字符串,username是数据库的用户名,passwd是数据库的密码。
(4)建立statement对象或者PreparedStatement对象。
(5)执行sql语句。
(6)获得结果集resultSet对象。
(7)依次关闭resultSet、statement、PreparedStatement、Connection对象,释放所占用的资源。
jdbc处理事务采用哪种方法?
一个事务是由一条或多条sql语句组成的不可分割的工作单元,只有当事务中的所有sql语句都正常执行完毕,事务才能被提交给数据库。在jdbc中,一般通过commit()或者rollback()方法结束事务的操作。其中,commit()指的是事务中的提交,rollback指的是事务的回滚,多用于在事务处理的过程中发生异常的情况。这两种方法都位于java.sql.connection()类中。一般而言,程序默认自动提交,即操作成功后,程序自动调用commit(),否则调用rollback()。
当然,在jdbc中也可以调用setAutoCommit(false)方法来关掉自动提交,将多个数据库操作的表达式作为一个事务,当操作完成后调用commit()整体提交,如果其中一个数据库的操作出现问题,就会抛出异常而不会调用commit(),在这种情况下就可以在异常捕获代码段中加入rollback()实现事务的回滚。采用此种方法可以在数据库多次操作后,数据仍保持一致性。
java有哪些事务隔离级别?
为了解决与多线程同时请求同一个资源的相关问题,事务之间通过锁相互隔离开。如今,多数主流的数据库都支持不同类型的锁,因此,javaAPI支持不同类型的事务,它们由connection对象指派或确定,在jdbc中,事务的隔离级别主要分为以下5种:
(1)TRANSACTION_NONE_JDB不支持事务
(2)TRANSACTION_READ_UNCOMMIT 未提交读,一个事务可以读取另一个事务未提交的数据,并且不可重复读和虚读都是允许的。
(3)TRANSACTION_READ_COMMIT 已提交读,一个事务不能读取"脏"数据,但是允许不可重复读和虚读。
(4)TRANSACTION_REPEATABLE_READ 可重复读,一个事务能重复读取已经读过的数据,不允许脏读,还可以虚读。
(5)TRANSACTION_SERIALIZETABLE 可序列化,事务的最高隔离级别,不允许脏读,不可重复读,虚读的发生。
(脏读,一个事务读取另一个事务未提交的数据,可重复读,一个事务的操作导致另一个事务前后两次读取的数据不同,虚读,一个事务的操作导致另一个事务前后两次查询的结果数据量不同)
事务的隔离级别越高,为了躲避重复耗费的精力更多。在jdbc中,可以通过Connection对象的conn.setTRANSACTIONlevel()方法来设置事务隔离级别,也可以通过conn.getTRANSACTIONIsolation()方法来查看事务的隔离级别。
class.forname()的作用是什么?
在java语言中,任何类只有被装载到JVM上才能运行。class.forname()的作用就是把类装载到JVM中,它会返回一个与带有给定字符串的类名的类或接口相关联的一个class对象,并且jvm会加载这个类,同时JVM会加载该类的静态代码段。
在使用jdbc连接数据库之前,一般都会调用class.forname("com.mysql.jdbc.driver")来加载数据库驱动,那么是否一定要使用这种方法呢?如果是,为什么?其实,不一定非要使用这种方法来加载数据库,也可以使用其他的方法来加载数据库,例如:Test t = (test)Class.forname().newinstance()语句和Test t = new Test()就具有相同的效果,所以使用new也可以,但二者的区别也非常明显:创建对象的方式不同。前者使用的是类加载机制,后者使用的是创建新的类。使用第一种方式会使程序具有更好的扩展性。例如:一个软件在开发出来后会被多个公司使用,每家的公司处理流程大致相同,只有个别公司的业务逻辑不通,这时,完全可以把不同的地方抽象出来定义成一个接口BussinessInterface,针对每个公司不同的业务逻辑可以创建不同的实现类sub1,sub2,sub3等。通过创建不同的子类就可以实现不同的需求。为了达到良好的可扩展性,可以把子类采用配置文件的方式放入XML,然后在采用BussinessInterface b = (bussinessInterface)Class.forname(classname).newInstance()创建实例即可提高开发人员的开发效率。当以后再有新的需求时,即使开发了新的子类,也不需要修改创建实例的代码,只需要修改配置文件即可,从而提高了程序的可扩展性。
JDBC规范中要求Driver类在使用前必须向DriverManager注册自己,所以,当执行Class.forname("com.mysql.jdbc.Driver")时,JVM会加载名字为"com.mysql.jdbc.Driver"对应的Driver类,而com.mysql.Driver类的实现如下:
。。。。。。
try{
}
catch(){
}
在调用class.forname()时,driver类被加载了,由于该类的静态代码也被执行了,所以Drive也被注册到了DriverManager()中。
statement和preparedstatement与callablestatement有什么区别?
statement用来执行不带参数的简单的sql语句,每次执行sql语句时,数据库都要编译sql语句,一个最简单的sql语句如下:
statement stmt = conn.getStatement();
stmt.executeUpdate("insert into client values(‘aa‘,‘aaaa‘)");
prepardStatement表示预编译的sql语句的对象,用于执行不带参数的预编译sql语句。
callableStatement则提供了用来执行数据库调取存储过程的方法。如果有输出参数注册,就说明是输出参数。
虽然statement和preparedStatement能够实现相同的功能,但相比之下,preparedstatement具有以下优点:
(1)效率更高。使用preparedstatement对象执行sql命令,该命令会被数据库进行解析和编译,然后放到命令缓冲区中。然后,当再次处理同一个对象的同一个命令时,由于在缓冲区中能够发现预编译的命令,只需要解析一次,不需要再次编译了,是可以重复使用的,能够有效提高系统性能,因此,如果要执行插入、更新、删除等操作时,最好使用preparedStatement即可。鉴于此,preparedStatement适用于存在大量用户的企业级应用软件中。
(2)代码可读性和可维护性更好。以下是使用statement和preparedstatement来实现的sql命令,明显可以看出preparedstatement的可读性更好。
①stmt.executeUpdate("insert into t(coll,col2) colls values(‘"+var1+"‘,‘"+var2+"‘‘)");
②perstmt=com.prepareStatement("insert into tb_name(coll,col2) values(?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
(3)安全性更好。使用preparedstatement能够有效预防sql注入问题,所谓sql注入是指把sql命令插入到web表单递交或输入域名或页面请求的查询字符串中,最终达到欺骗服务器,达到执行恶意sql命令的目的。注入只对sql命令的编译过程有破坏作用,在执行阶段只是把输入串作为数据处理,不会对sql语句进行解析,因此可以有效避免sql注入问题。
callablestatement是由prepareCall()方法创建的,它为所有的DBMS(DataBase Management
System)数据库管理系统提供一种标准的数据库调用存储过程的方法。其对存储过程的调用有两种方式,一种是带结果参数的,一种是不带结果参数的,结果参数是输出参数,是存储过程的返回值。这两种方式都可以带有数量不同的输入参数(IN参数)、输出参数(Out参数)和输入输出参数(INOut参数)。
getString方法和getObject方法有什么区别?
jdbc提供了getString,getInt,getData等方法从resultset中获取数据,当结果集返回的数据量很小时,使用这些方法完全能够满足需求,但是当从结果集中返回的数据量非常多时,使用这些方法就会抛出异常:ORACLE Exception
ORA-0100 miximum opencursors execeeded(在ORACLE数据中),使用getObject就可以解决这些问题。
getString(),getin()等方法被调用时,程序会一次性将数据读取到内存中,然后通过调用resultset的next()或getString()等方法来获取数据,当数据量大到内存中放不下时,就会抛出异常,而使用getObject方法就不会发生这种问题,因为getobject方法不会一次性将数据读取到内存中,每次使用时都会去数据库中获取数据,所以不会发生数据量过大的问题。
使用jdbc需要注意哪些问题?
使用jdbc编程时,首先要建立数据库的连接,才能完成对数据库的访问,由于与数据库的连接是非常重要的资源。jdbc连接池提供了jdbc连接定义和数量有限的连接,如果连接数量不够,就需要长时间的等待,错误的关闭和释放jdbc会等待回收无效的jdbc,只有正确的关闭和释放jdbc连接,jdbc资源才能快速的重复使用,从而能够提高系统的性能。因此在编程时,应该保证释放不在使用的连接。
一般来讲,在使用jdbc访问数据库时,createStatement和preparedStatement最好放在循环的外面,而且使用了这些statement之后需要及时关闭。最好是在使用ececuteQuery或executeUpdata之后,如果不需要再使用结果集中的数据,最好马上释放statemnet,因为每次调用conn.createstatement()或者conn.preparedStatement()时,相当于再数据库中创建了一个(游标)cursor,如果把这两方法放到循环中就会导致不停的创建curtor,如果不能及时释放,就会导致抛出异常。
什么是JDO?
java data object(java数据对象)是一个用于存取某种数据仓库对象的标准化API,它使开发人员能够间接的访问数据库。
JDO是JDBC的一个补充,它提供了一个透明的存储对象。对于开发人员来说,数据存储对象不需要额外的代码(例如:jdbc API),它把这些繁琐的任务转移到了JDO产品提供商身上,使开发人员解脱出来,使精力和时间集中在业务逻辑上。另外,相较于jdbc,JDO更灵活,更通用,它提供了所有数据底层的存储功能,使得应用可移植性更强。
jdbc和hibernate有什么区别?
hibernate是jdbc的封装,它通过配置文件的方式将数据库的连接参数放入XML文件中,而对数据库的访问还是通过jdbc实现。
hibernate是一个持久层框架,它将表的信息映射到XML文件中,然后再从XML文件中映射到持久化类里,这样就可以使用hibernate自带的查询语言HQL(Hibernate Query Language)。hibernate的HQL查询语言返回的是一个list<object[.]>类,而jdbc的statement返回的是一个结果集(resultset),而且有时候需要自己封装到list中。hibernate具有访问层,(DAO类层,Data Access Object,数据访问接口),HQL查询语句只能在DAO层使用,再往上层不会出现查询语句,而jdbc可以随时连接随时访问。例如:如果有50个类都有查询语句,如果表名改变了,那么使用jdbc方式就需要重写所有查询语句,而使用hibernate只需要需改DAO层的类即可。所以Hibernate具有很好的维护性和扩展性。
本文出自 “java学习方向” 博客,谢绝转载!
以上是关于jdbc的相关知识的主要内容,如果未能解决你的问题,请参考以下文章