




已阅读5页,还剩43页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JDBC,学习目标,1、JDBC介绍 2、JDBC应用程序开发步骤 3、元数据与异常 4、事务处理 5、JDBC相关内容,1、JDBC介绍,What is JDBC? Five important interfaces of JDBC The type of JDBC,What is JDBC?,JDBC(Java Database Connectivity)是基于JAVA语言访问数据库的一种技术。 JDBC的设计思想:由SUN公司(JCP)提供访问数据库的接口,由数据库厂商提供对这些接口的实现,程序员编程时都是针对接口进行编程的。 JDBC包括一套JDBC的API和一套程序员和数据库厂商都必须去遵守的规范。 java.sql包:提供访问数据库基本的功能 javax.sql包:提供扩展的功能,What is JDBC?(续),数据库中间件 JDBC可以做些什么? 连接到数据库 在Java app中执行SQL命令 处理结果。,Five important interfaces of JDBC,Connection:特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果 Statement:用于执行静态 SQL 语句并返回它所生成结果的对象 PreparedStatement:表示预编译的 SQL 语句的对象 CallableStatement:用于执行 SQL 存储过程的接口 ResultSet:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成,The type of JDBC,Type1:JDBC-ODBC bridge 要求客户端必须安装ODBC驱动 执行效率比较低,对于那些大数据量存取的应用是不适合的 适用于快速的原型系统,没有提供JDBC驱动的数据库如Access(Desktop Database),Type2:Java to native API 这种驱动比起JDBC-ODBC桥执行效率略有提高.但是,它仍然需要在客户端加载数据库厂商提供的代码库.这样就不适合基于internet的应用,Type3:Java to Net 适合那种需要同时连接多个不同种类的数据库并且对并发连接要求高的应用,Type4:Java to Native Database 最高的性能,通过自己的本地协议直接与数据库引擎通信,2、JDBC应用程序开发步骤,2.1、注册JDBC驱动程序 2.2、创建数据库连接(获取Connection的方法) 2.3、创建SQL(存储过程)语句的对象 /2.4、操作 resultset 对象(可有可无) 2.5、关闭JDBC资源,2.1、注册JDBC驱动程序,Class.forName(“oracle.jdbc.driver.OracleDriver“);,2.2、创建数据库连接(获取Connection的方法),2.2.1、通过DriverManager获取 2.2.2、通过Driver直接获取(不推荐使用),2.2.1、通过DriverManager获取,Connection conn = DriverManager.getConnection(url, “username“, “password“); JDBC的URL协议名子协议名数据源名。 a 协议名总是“jdbc”。 b 子协议名由JDBC驱动程序的编写者决定。 c 数据源名也可能包含用户与口令等信息;这些信息也可单独提供。 几种常见的数据库连接,几种常见的数据库连接,-oracle- 驱动:oracle.jdbc.driver.OracleDriver URL:jdbc:oracle:thin:dbname 注:machine_name:数据库所在的机器的名称; port:端口号,默认是1521 -mysql- 驱动:org.gjt.mm.mysql.Driver or: com.mysql.jdbc.Driver URL:jdbc:mysql:/dbname 注:machine_name:数据库所在的机器的名称; port:端口号,默认3306 -SQL Server- 驱动:com.microsoft.jdbc.sqlserver.SQLServerDriver URL:jdbc:microsoft:sqlserver:/;DatabaseName= 注:machine_name:数据库所在的机器的名称; port:端口号,默认是1433,2.2.2 通过Driver直接获取(不推荐使用),public static Connection getConnection() String url = “jdbc:mysql:/localhost:3306/test“; String userName = “root“; String password = “1234“; Properties user = new Properties(); /key为user,password,不同的数据库的driver的key不是固定的 /视乎driver的实现者 user.setProperty(“user“, userName); user.setProperty(“password“, password); Driver driver=null; Connection conn=null; try driver = new com.mysql.jdbc.Driver(); conn = driver.connect(url, user); catch (Exception e) e.printStackTrace(); return conn; ,2.3 创建SQL(存储过程)语句的对象,2.3.1、创建Statement对象 2.3.2、 PreparedStatement 2.3.3、 CallableStatement 2.3.4、 Statement接口的比较,2.3.1、创建Statement对象,Statement stm = con.createStatement(); 主要方法 执行查询SQL语句(返回结果集) ResultSet executeQuery(String sql) throws SQLException; 执行更新SQL语句(返回受影响的行数) int rows = executeUpdate(String sql) throws SQLException 万能执行SQL语句(如果第一个结果为 ResultSet对象,则返回true;如果其为更新计数或者不存在任何结果,则返回false) boolean flag=stmt.execute(sql); ResultSet rs=null; int rows=0; if(flag) rs=stmt.getResultSet(); else rows=stmt.getUpdateCount(); ,2.3.2、 PreparedStatement,1、用来处理SQL结构、关键部分相同的SQL语句 2、pstmt=conn.prepareStatement(sql); 3、例子 String sql = “SELECT * FROM login WHERE username=?“; /?代表一个占位符合,它的值是待定的。 pstmt=conn.prepareStatement(sql); /下面的语句设置?的值 /第一参数是?的索引位置 /第二参数:把?的值设置成这个参数 pstmt.setString(1, “zll“); rs=pstmt.executeQuery(); String sql = “INSERT INTO login(username,password) VALUES(?,?)“; pstmt=conn.prepareStatement(sql); pstmt.setString(1, “zczll“); pstmt.setString(2, “q“); pstmt.executeUpdate();,2.3.3、 CallableStatement,1、用来执行存储过程 2、CallableStatement cstmt=con.prepareCall(sql); 3、例子 String sql = “CALL getTotalStudent(?,?)“; CallableStatement cstmt=con.prepareCall(sql); / 设置OUT和IN参数 cstmt.registerOutParameter(1, java.sql.Types.INTEGER); cstmt.setString(2, “xxx“); 创建一个存储过程 in:参数从Java程序传到数据库的存储过程 out:反过来 SQl语句中创建存储过程: 1) delimiter / 2) CREATE PROCEDURE getTotalStudent(OUT totalStudent integer(11),IN sex char(2) BEGIN SELECT count(*) INTO totalStudent FROM student WHERE stu_sex LIKE sex; END/ 3) delimiter ;,2.3.4、 Statement接口的比较,Statement接口的选择及建议,选择:没有最好,只有最合适! 建议:可以移植性好首先考虑的条件!然后再考虑性能问题!,2.4、How to handle resultset,通过index获取字段的值。 String getString(int columnIndex) /int类型的参数 SELECT * FROM login;/默认顺序按表里的定义顺序 rs.getString(3);/password SELECT id,username,password FROM student; rs.getString(3);/password columnIndex:select子句中该字段的索引位置 通过字段名获取字段的值。 String getString(String columnName) /String类型的参数 以 Java 编程语言中 String 的形式检索此 ResultSet 对象的当前行中指定列的值。 rs.getString(“username“);/ username rs.getInt(“id“);/id Java类型到SQL类型的映射。,2.5、关闭JDBC资源,首先关闭记录集; 其次关闭Statement; 最后关闭连接对象。 例: if(rs !=null) tryrs.close();catch(SQLException e) e.printStackTrace(); if(stm!=null)trystm.close(); catch(SQLException e)e.printStackTrace(); if(con!=null)trycon.close(); catch(SQLException e)e.printStackTrace();,3、元数据与异常,3.1、元数据 3.2、异常,3.1、元数据,元数据:描述数据的数据。 元数据:开发IDE工具、中间件服务器开发人员需要重点掌握。对于普通的应用系统开发者,只需了解即可。 DatabaseMetaData接口,用于提供关于数据库的整体综合信息。 DatabaseMetaData dmd=conn.getMetaData(); DatabaseMetaData:整个数据库的元数据 数据库版本、名称 数据库驱动程序的版本、名称 数据库支持的操作(事务隔离级别、结果集支持的类型等) ResultSetMetaData ,用于描述结果集本身的信息, 表结构(包括有那些字段,字段的类型等信息) 即可用于获取关于 ResultSet对象中列的类型和属性信息的对象。 ResultSetMetaData rsmd=rs.getMetaData();,3.2、异常,SQLException:致命性的错误,如,表不存在等,主键重复等。 int getErrorCode() MySQL:1062 DB2:803 Oracle:1 /Vendor specific 依赖于具体的数据库厂商,返回数据库厂商特定的错误代码。 SQLException getNextException() 检索到此 SQLException 对象的异常链。 如果不存在,则返回 null。 String getSQLState() 依赖于规范 ,返回SQL99或者XOPEN中规定的错误代码。 出现SQLException的情况: 网络连接失败 SQL语句存在语法错误 不支持的函数调用 引用不存在的字段 插入主键相同的行 其他 SQLWarning(非致命性的错误,提供关于数据库访问警告信息的异常,很多时候无需程序员处理,是SQLException类的子类) 抛出SQLWarning之后数据库操作是否成功,与特定的数据库Driver相关,4、事务处理,4.1、What is Transaction 4.2、JDBC API中使用事务处理步骤 4.3、并发控制,4.1、What is Transaction,事务处理:一系列的动作作为一个不可分解的操作。 ACID 属性:Atomic Consistent Isolated Durable 1 原子性 ALL-NOTHING 事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。 2 一致性 事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。 3 分离性 分离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。 4 持久性 持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失即一旦一个事务提交,DBMS保证它对数据库中数据的改变应该是永久性的,耐得住任何系统故障。持久性通过数据库备份和恢复来保证。,4.2、JDBC API中使用事务处理步骤,默认是自动提交:每发送一条SQL语句都是自动提交的! 1) 用false作为参数调用Connection setAutoCommit方法; 2) 执行一或多个关于数据库的操作; 3) 调用commit方法完成改变; 4) 如果发生错误,恢复上次提交后的改变, 调用rollback方法; 5) 用true作为参数调用setAutoCommit方法; 恢复自动提交事务开关。,4.3、并发控制,4.3.1、事务隔离级别 4.3.2、隔离级别的现象 4.3.3、设置隔离级别,4.3.1、事务隔离级别,未提交读( read uncommitted ) 隔离事务的最低级别,只能保证不读取物理上损坏的数据。 已提交读( read committed ) 大多数数据库引擎的默认级别。当一个事务运行在这个隔离级别时, 一个查询只能看到查询开始之前提交的数据,而永远无法看到未提交的数据,或者是在查询执行时其他并行的事务提交做的改变。 可重复读( repeatable read ) 不会脏读和非重复读,可能发生幻像读 可串行化( serializable ) 隔离事务的最高级别,事务之间完全隔离。,4.3.2、隔离级别的现象,脏读(Dirty Read):当一个事务的中间(未提交的)结果对另一个事务可见时就会发生这种情况。例如:事务读到无提交的数据. 不可重复读(Unrepeatable Read):当一个事务读取一个数据项,然后重新读取这个数据项并看到不同的值时就是发生了这种情况。例如:在同一事务中两次读取同一数据项读到不同的数据. 幻读(Phantom Read):当一个事务执行返回多个行的查询,稍后再次执行同一个查询并看到第一次执行该查询没出现的额外行时就是发生了这种情况。例如:在同一事务总相同的查询条件不同的时间点执行返回不同的结果集,4.3.3、设置隔离级别,数据库支持的隔离级别是由数据库的设计者决定的! 设置隔离级别方法:setTransactionIsolation 隔离级别静态变量 TRANSACTION_NONE:说明不支持事务(毫无意义)。 TRANSACTION_READ_UNCOMMITTED:说明一个事务在提交前其变化对于其他事务来说是可见的。这样脏读、不可重复的读和幻读都是允许的。 TRANSACTION_READ_COMMITTED:说明读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和幻读产生。 TRANSACTION_REPEATABLE_READ:说明事务保证能够再次读取相同的数据而不会失败,但幻读仍然会出现。 TRANSACTION_SERIALIZABLE:串行化读,是最高的事务级别,它防止脏读、不可重复的读和幻读。,隔离级别说明,重要提示:,对于大多数数据库,缺省的隔离级别为“已提交读”,这是个很好的缺省选择,因为它阻止事务在事务中的任何给定的点看到应用程序数据的不一致视图。“已提交读”是一个很不错的隔离级别,用于大多数典型的短事务,比如获取报表数据或获取要显示给用户的数据的时候(多半是作为 Web 请求的结果),也用于将新数据插入到数据库的情况。这个隔离级别取得了很好的性能和安全性的折中。在数据一致性绝对重要的情况下,比如审核记帐数据库以确保一个帐户的所有借方金额和贷方金额的总数等于它目前的余额时,可能还需要防止创建新行。这种情况下就需要使用“可串行化”隔离级别。 一般来说,数据一致性问题比性能问题更严重。如果拿不准,应该以采用保守的策略,选择一个较高的隔离级别。,5、JDBC相关内容,5.1、JDBC2.0 new feature 5.2、 JNDI 5.3、 DataSource 5.4、 Connection Pool,5.1、JDBC2.0 new feature,5.1.1、可滚动可更新的结果集 5.1.2、批量更新,5.1.1、可滚动可更新的结果集,Connection.createStatement(int resultSetType, int resultSetConcurrency) 参数: 第一个参数resultSetType - 结果集类型,它是 ResultSet.TYPE_FORWARD_ONLY:游标只能向前移动;ResultSet.TYPE_SCROLL_INSENSITIVE:可滚动但通常不受其他的更改影响的 ResultSet 对象的类型;ResultSet.TYPE_SCROLL_SENSITIVE可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。 第二个参数resultSetConcurrency - 并发类型;它是 ResultSet.CONCUR_READ_ONLY:只读;ResultSet.CONCUR_UPDATABLE:可更新,5.1.1、可滚动可更新的结果集(续),查询语句的限制: 查询语句只能查询一张表 查询语句不能包含连接操作和group by子句 查询语句要把表的主键查询出来如果是在结果集上执行插入操作,则还有如下限制: 查询语句要查询出表中所有非空列; 查询语句要查询出表中所有没有默认值的列。 增删改操作: 增 调用ResultSet.moveToInsertRow()来移动到Insert row 调用ResultSet.updateXXX方法来更新insert row的某列的值 调用ResultSet.insertRow()来插入数据 删 确定要删除的记录的位置 调用ResultSet.deleteRow()来删除数据 改 确定要更新的记录的位置 调用ResultSet.updateXXX方法来更新当前记录的某列的值 调用ResultSet.updateRow()来更新数据,5.1.2、批量更新,批量更新允许用户一次提交多条更新操作,一起被处理。减少网络通信次数,提高效率。 使用Statement Statement.addBatch(String sql); Statement.executeBatch();/返回一个int,影响的记录的个数 使用PreparedStatement PreparedStatement.addBatch(); PreparedStatement.executeBatch(); 何时使用Statement与PreparedStatement? 如果批量中包含的SQL语句具有相同的结构,则既可以使用PreparedStatement来执行批量更新也可以使用Statement来执行;但如果批量中包含的SQL语句结构不同,则只能用Statement来执行批量更新。,5.2、 JNDI,JNDI(Java Naming and Directory Interface), 能够提供注册和访问远程服务的API. 相应的API在javax.naming包中.JNDI API为应用程序提供了一种统一的访问远程服务的方式. 使用JNDI API , 应用程序能够通过指定一个逻辑的名称来访问一个DataSource(当然可以是其他类型的远程对象)对象。,5.3、 DataSource,5.3.1、What is DataSource? 5.3.2、取数据库连接的方式,5.3.1、What is DataSource?,作为 DriverManager 设施的替代项,DataSource 对象是获取连接的首选方法。实现 DataSource 接口的对象通常在基于 Java(TM) Naming and Directory Interface (JNDI) API 的命名服务中注册。增强程序的可移植性;DataSource是一种方便的手段. DataSource 接口由驱动程序供应商实现。共有三种类型的实现: 基本实现 - 生成标准 Connection 对象(此时DataSource的作用与DriverManager完全一样)。 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池 管理器一起使用。 分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,并且几乎始终参与连接池。此实现与中间层事务管理器一起使用,并且几乎始终与连接池管理器一起使用。,5.3.2、取数据库连接的方式,第一种: Class.forName(“数据库驱动类的名字“);/ 注册 Connection con = DriverManager.getConnection(url,userName,password); 编码本身对底层的数据源很依赖,可移植性差 第二
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论