一、连接各种数据库方式速查表 下面罗列了各种数据库使用JDBC连接的方式,可以作为一个手册使用。 1、Oracle8/8i/9i数据库(thin模式)
2、DB2数据库
3、Sql Server7.0/2000数据库
4、Sybase数据库
5、Informix数据库
6、MySQL数据库
7、PostgreSQL数据库
8、access数据库直连用ODBC的
二、JDBC连接MySql方式 下面是使用JDBC连接MySql的一个小的教程 1、查找驱动程序 MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置。 2、动态指定classpath 如果需要执行时动态指定classpath,就在执行时采用-cp方式。否则将上面的.jar文件加入到classpath环境变量中。 3、加载驱动程序
4、设置连接的url
三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧 1、在客户端软件开发中使用Thin驱动程序 在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯。为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的。但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下,Thin驱动程序的性能都超过了OCI驱动程序。 2、关闭自动提交功能,提高系统性能 在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的。为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示: conn.setAutoCommit(false); 值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。 3、在动态SQL或有时间限制的命令中使用Statement对象 在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快。然而,我进行的测试表明,在客户端软件中,情况并非如此。因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象。 此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令。因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单。 4、利用helper函数对动态SQL命令进行格式化 在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题。例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法。与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式。 5、利用PreparedStatement对象提高数据库的总体效率 在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,它就会被再解析一次,但不会被再次编译。在缓冲区中可以发现预编译的命令,并且可以重新使用。在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。 6、在成批处理重复的插入或更新操作中使用PreparedStatement对象 如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():
调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。 7、使用Oracle locator方法插入、更新大对象(LOB) Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值。由于存在这二个问题,因此,我建议使用locator的方法来插入、更新或获取LOB的值。 8、使用SQL92语法调用存储过程 在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL92。 9、使用Object SQL将对象模式转移到数据库中 既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法。尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。 10、利用SQL完成数据库内的操作 我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求,而不是使用Java等过程化的编程语言。 如果编程人员要在一个表中查找许多行,结果中的每个行都会查找其他表中的数据,最后,编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务,何必要让数据在网上流来流去的?我建议用户认真学习如何最大限度地发挥SQL的功能。 |
两天的时间全都耗在这里了,其实这并不是很复杂的事情但还是把我搞了半天.
|
教程:JDBC 入门 作者:Maydene Fisher 翻译:comer 你需要做的第一事情是你与想要使用的 DBMS 建立一个连接。这包含 2 个步骤:装载驱动程序并建立连接。 装载驱动程序 装载驱动程序只需要非常简单的一行代码。例如,你想要使用 JDBC-ODBC 桥驱动程序, 可以用下列代码装载它: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 你的驱动程序文档将告诉你应该使用的类名。例如, 如果类名是 jdbc.DriverXYZ ,你将用代码以下的代码装载驱动程序: Class.forName("jdbc.DriverXYZ"); 你不需要创建一个驱动程序类的实例并且用 DriverManager 登记它,因为调用 Class.forName 将自动将加载驱动程序类。如果你曾自己创建实例,你将创建一个不必要的副本,但它不会带来什么坏处。 加载 Driver 类后,它们即可用来与数据库建立连接。 建立连接 第二步就是用适当的驱动程序类与 DBMS 建立一个连接。下列代码是一般的做法: Connection con = DriverManager.getConnection(url, "myLogin", "myPassword"); 这个步骤也非常简单,最难的是怎么提供 url。如果你正在使用 JDBC-ODBC 桥, JDBC URL 将以 jdbc:odbc 开始:余下 URL 通常是你的数据源名字或数据库系统。因此,假设你正在使用 ODBC 存取一个叫 "Fred" 的 ODBC 数据源,你的 JDBC URL 是 jdbc:odbc:Fred 。把 "myLogin" 及 "myPassword" 替换为你登陆 DBMS 的用户名及口令。如果你登陆数据库系统的用户名为 "Fernanda" 口令为 "J8",只需下面的 2 行代码就可以建立一个连接: String url = "jdbc:odbc:Fred"; Connection con = DriverManager.getConnection(url,"Fernanda", "J8"); 如果你使用的是第三方开发了的 JDBC驱动程序,文档将告诉你该使用什么 subprotocol, 就是在 JDBC URL 中放在 jdbc 后面的部分。例如, 如果驱动程序开发者注册了 acme 作为 subprotocol, JDBC URL 的第一和第二部分将是 jdbc:acme。驱动程序文档也会告诉你余下 JDBC URL 的格式。JDBC URL 最后一部分提供了定位数据库的信息。 如果你装载的驱动程序识别了提供给 DriverManager.getConnection 的 JDBC URL ,那个驱动程序将根据 JDBC URL 建立一个到指定 DBMS 的连接。正如名称所示,DriverManager 类在幕后为你管理建立连接的所有细节。除非你是正在写驱动程序,你可能无需使用此类的其它任何方法,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。 DriverManager.getConnection 方法返回一个打开的连接,你可以使用此连接创建 JDBC statements 并发送 SQL 语句到数据库。在前面的例子里,con 对象是一个打开的连接,并且我们要在以后的例子里使用它。 JDBC 入门 -- 设置表 创建表 首先,我们在我们的示例数据库创建其中一张表 COFFEES,包含在咖啡店所卖咖啡的必要的信息,包括咖啡名字,他们的价格,本星期卖了多少磅及迄今为止卖的数目。关于 COFFEES 表我们以后会详细描述,如下: COF_NAME SUP_ID PRICE SALES TOTAL Colombian 101 7.99 0 0 French_Roast 49 8.99 0 0 Espresso 150 9.99 0 0 Colombian_Decaf 101 8.99 0 0 French_Roast_Decaf 49 9.99 0 0 存储咖啡名的列是 COF_NAME,它的 SQL 数据类型是 VARCHAR,最大的长度为 32 个字符。因为我们所卖的每种类型咖啡都使用不同的名字,名字可用于作为唯一识别咖啡的标识,因此可用于作主键。第二个列叫 SUP_ID,用于保存咖啡供应商标识;其 SQL 数据类型为 INTEGER。第 3 列叫 PRICE,因为它需要保存带小数的十进制数,因此它的 SQL 类型为 FLOAT。(注意,通常钱的 SQL 类型为 DECIMAL 或 NUMERIC,但在不同 DBMSs 间存在差异,为了避免于老版本的 JDBC 的不兼容性在本教程我们采用更标准的 FLOAT 类型)SALES 列的 SQL 类型为 INTEGER,其值为本星期所卖咖啡的磅数。最后一列,TOTAL 的 SQL 类型为 INTEGER,保存了迄今为止所卖咖啡的总磅数。 数据库里的第二个表 SUPPLIERS,保存了每个供应商的信息: SUP_ID SUP_NAME STREET CITY STATE ZIP 101 Acme, Inc. 99 Market Street Groundsville CA 95199 49 Superior Coffee 1 Party Place Mendocino CA 95460 150 The High Ground 100 Coffee Lane Meadows CA 93966 COFFEES 跟 SUPPLIERS 都包含列 SUP_ID,它意味着可以用 SELECT 语句从这两张表中取得有关信息。列 SUP_ID 是 SUPPLIERS 表的主键,用于唯一识别每个咖啡供应商。在 COFFEES 表中,SUP_ID 列被称外键。注意每个 SUP_ID 值在 SUPPLIERS 表里只出现一次;这对主键是必须的。在 COFFEES 表里,它作为外键,显然它可以有重复的 SUP_ID 值,因为同一供应商可以提供很多种的咖啡。在本节的最后,你将看见如何在 SELECT 语句中使用主键及外键的一个例子。 下面的 SQL 语句用于创建 COFFEES 表。列由列名跟空格跟 SQL 类型组成。列(包括列名及其 SQL 类型)跟下一个之间用逗号分隔。VARCHAR 类型创建定义了最大长度, 因此它需要有一个参数来表示最大长度。参数必须在类型后面的括号内。SQL 语句如下,列 COF_NAME 的长度 被限定为不得超过 32 个字符: CREATE TABLE COFFEES (COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, SALES INTEGER, TOTAL INTEGER) 这些代码不带 DBMS 语句结束符, 因为每个 DBMS 都可能不同。例如, Oracle 使用一个分号 (;) 作为语句的结束,而 Sybase 使用 go。你所使用的驱动程序会自动提供合适的语句结束符,因此你无须把它包括在你的 JDBC 代码中。 另外,我们应该指出的的是 SQL 语句的格式。在 CREATE TABLE 语句中,关键字采用大写字符,并且每个项目都另起一行。SQL 并没有此要求;仅仅是为了更容易阅读。SQL 标准是不区分关键词的大小写的, 因此,如下例中的 SELECT 语句可以有多种写法。因此下面两个不同写法的语句对 SQL 来说是一样的。 SELECT First_Name, Last_Name FROM Employees WHERE Last_Name LIKE "Washington" select First_Name, Last_Name from Employees where Last_Name like "Washington" 然而,引号里的内容是区分大小写的:在名字"Washington" 里 "W" 必须被大写,并且余下的字符必须是小写的。 对于标识,不同的 DBMS 有不同的要求,例如, 某些 DBMSs 要求那些列名及表名必须跟创建时的一样,有些则没有此要求。为安全起见,我们全部使用大写标识如 COFFEES、SUPPLIERS,因为我们是那样定义他们的。 到止我们写了创建 COFFEES 表的 SQL 语句。现在我们在它外面加上引号(使它成为字符串),并且字符串赋值给变量 createTableCoffees,在以后的 JDBC 代码中我们可以使用此变量。正如看到的,DBMS 并不在意分行,但对 Java 语言来,String 对象分行是通不过编译的。因而,我们可以用加号 (+) 把每一行的串连接。 String createTableCoffees = "CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)"; 我们在 CREATE TABLE 语句中使用的数据类型是通用的 SQL 类型(也称 JDBC 类型)它们在类 java.sql.Types 中定义。DBMSs 通常使用这些标准的类型,因此,当你要尝试一些 JDBC 应用程序时,你可以直接使用 CreateCoffees.java 应用程序,它使用了 CREATE TABLE 语句。如果你的 DBMS 使用了它的自己的本地的类型名字,我们为你供应其它的应用程序,我们将在后面详细解释。 在运用任何应用程序前,当然,我们将让你了解 JDBC 的基础。 创建 JDBC Statements 对象 Statement 对象用于把 SQL 语句发送到 DBMS 。你只须简单地创建一个 Statement 对象并且然后执行它,使用适当的方法执行你发送的 SQL 语句。对 SELECT 语句来说,可以使用 executeQuery。要创建或修改表的语句,使用的方法是 executeUpdate。 需要一个活跃的连接的来创建 Statement 对象的实例。在下面的例子中,我们使用我们的 Connection 对象 con 创建 Statement 对象 stmt: Statement stmt = con.createStatement(); 到此 stmt 已经存在了,但它还没有把 SQL 语句传递到 DBMS。我们需要提供 SQL 语句作为参数提供给我们使用的 Statement 的方法。例如,在下面的代码段里,我们使用上面例子中的 SQL 语句作为 executeUpdate 的参数: stmt.executeUpdate("CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)"); 因为我们已经把 SQL 语句赋给了 createTableCoffees 变量,我们可以如下方式书写代码: stmt.executeUpdate(createTableCoffees); 执行语句 我们使用 executeUpdate 方法是因为在 createTableCoffees 中的 SQL 语句是 DDL (数据定义语言)语句。创建表,改变表,删除表都是 DDL 语句的例子,要用 executeUpdate 方法来执行。你也可以从它的名字里看出,方法 executeUpdate 也被用于执行更新表 SQL 语句。实际上,相对于创建表来说,executeUpdate 用于更新表的时间更多,因为表只需要创建一次,但经常被更新。 被使用最多的执行 SQL 语句的方法是 executeQuery。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。马上你将看到如何使用这个方法。 在表中输入数据 我们已经显示了如何通过指定列名、数据类型来创建表 COFFEES,但是这仅仅建立表的结构。表还没有任何数据。我们将次输入一行数据到表中,提供每列的信息,注意插入的数据显示顺序跟表创建时候是一样的,既缺省顺序。 下列代码插入一个行数据,COF_NAME 的值为 Colombian,SUP_ID 为 101,PRICE 为 7.99,SALES 0,TOTAL 0。就象创建 COFFEES 表一样,我们创建一 Statement 对象,并执行 executeUpdate 方法。 因为 SQL 语句一行显示不下,因此我们把它分为两行,并用加号 (+) 相连。特别要注意的是,在 COFFEES 和 VALUES 之间要有空格。这个空格必须在引号之内并且要在 COFFEES 跟 VALUES 之间;没有这个空格,SQL 语句将被错误地被读作为 "INSERT INTO COFFEESVALUES ...",并且 DBMS 将寻找表 COFFEESVALUES。还要注意的是在 coffee name 上我们使用了单引号。 Statement stmt = con.createStatement(); stmt.executeUpdate( "INSERT INTO COFFEES " + "VALUES ('Colombian', 101, 7.99, 0, 0)"); 下面的代码把第二行插入到表 COFFEES 中。我们可以在使用 Statement 对象而无须为每次执行创建一个新的。 stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast', 49, 8.99, 0, 0)"); 剩下行的数据如下: stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Espresso', 150, 9.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)"); 从表中取得数据 既然表 COFFEES 中已经有数据了,我们就可以写一个 SELECT 语句来取得这些值。下面的 SQL 语句中星号 (*) 表示选择所有的列。因为没有用 WHERE 子句来限制所选的行,因此下面的 SQL 语句选择的是整个表。 SELECT * FROM COFFEES 结果是整个表的数据,如下: COF_NAME SUP_ID PRICE SALES TOTAL --------------- ------ ----- ----- ----- Colombian 101 7.99 0 0 French_Roast 49 8.99 0 0 Espresso 150 9.99 0 0 Colombian_Decaf 101 8.99 0 0 French_Roast_Decaf 49 9.99 0 0 如果你直接在数据库系统里输入 SQL 查询语句,你将在你的终端上看到如上的结果。当我们通过一个 Java 应用程序存取一个数据库时,正如我们马上要做的一样,我们需要检索结果以便我们能使用他们。你将在下一节看到如何实现。 这是 SELECT 语句的另一个例子,这将得到咖啡及其各自每磅单价的列表。 SELECT COF_NAME, PRICE FROM COFFEES 查询的结果集将具有如下形式: COF_NAME PRICE -------- ---------- ----- Colombian 7.99 French_Roast 8.99 Espresso 9.99 Colombian_Decaf 8.99 French_Roast_Decaf 9.99 上面 SELECT 语句取得了所有咖啡的名字及价格。而下面的 SELECT 语句限制那些每磅价格低于 $9.00 的咖啡才被选择。 SELECT COF_NAME, PRICE FROM COFFEES WHERE PRICE < 9.00 结果集将具有如下形式: COF_NAME PRICE -------- ------- ----- Colombian 7.99 French_Roast 8.99 Colombian Decaf 8.99 JDBC 入门 -- 开始 你需要做的第一事情是你要正确的安装。这包含下列几个步骤: 在你的计算机上安装 Java 和 JDBC Java 数据库连接 (JDBC) 是一个标准 SQL(Structured Query Language,结构化查询语言)数据库访问接口, 可以为多种关系数据库提供统一访问。JDBC(Java DataBase Connection,Java 数据库连接) 也提供一种基准,据此可以构建更高级的工具和接口。 目前的 JDK(Java Development Kit,Java 开发工具包)软件捆绑包括 JDBC 和 JDBC-ODBC(Open DataBase Connection,开放式数据库连接)桥。这些包也可独立得到,以跟 JDK 1.0 一起使用。应该注意的是,本文的示例使用了 JDBC 2.0 接口,需要 JDK 2.0 来运行,不能在 JDK 1.1 下运行。 你可以从 http://java.sun.com/products/JDK/CurrentRelease 找到最新版。 安装驱动程序 你的驱动程序应该有安装方法。为特定的 DBMSs 写的 JDBC 驱动程序安装时只要拷贝到你的计算机上就可以了。并不需要特殊的配置。 如果你下载的是 Solaris 或 Windows JDK1.1 版本,桥作为包 sun.jdbc.odbc 与 JDK 一起自动安装。有关安装和配置 ODBC 的信息,请咨询 ODBC 驱动程序厂商。桥无须特殊配置。有关客户机安装和配置信息,请咨询数据库厂商。 如果需要,安装数据库系统 如果你不能确认是否安装了数据库系统,你需要按照供应商的要求安装数据库。大多数用户都已经安装了数据库,可继续使用他们安装好的数据库。 配置数据库 我们假设数据库 COFFEEBREAK 已经存在。(创建一个数据库并不困难,但需要一定的权限并通常是由数据库管理员来做)你还需要在此数据库里创建本教程作为例子使用的表。我们有意限制表的大小跟及数目,以便于管理。 假设我们的数据库是在一个咖啡馆里使用, 咖啡豆按磅卖,而咖啡则以杯为单位。为了简单起见,还假定经营者只需要 2 张表,分别存放不同种类的咖啡及咖啡供应商的有关信息。 首先我们演示怎么打开一个 DBMS 连接, 及 JDBC 是怎么发送 SQL 语句到你的 DBMS。通过这些代码,我们将表明使用 JDBC 传递 SQL 语句到你的 DBMS 并处理返回的结果是非常简单的。 所有的代码在主要的几个 DBMS 产品做了测试。然而, 如果你使用 JDBC-ODBC 桥来连接旧版本 ODBC 驱动程序时,可能会遇到一些兼容性问题。 |
创建表 首先,我们在我们的示例数据库创建其中一张表 COFFEES,包含在咖啡店所卖咖啡的必要的信息,包括咖啡名字,他们的价格,本星期卖了多少磅及迄今为止卖的数目。关于 COFFEES 表我们以后会详细描述,如下: COF_NAME SUP_ID PRICE SALES TOTAL Colombian 101 7.99 0 0 French_Roast 49 8.99 0 0 Espresso 150 9.99 0 0 Colombian_Decaf 101 8.99 0 0 French_Roast_Decaf 49 9.99 0 0 存储咖啡名的列是 COF_NAME,它的 SQL 数据类型是 VARCHAR,最大的长度为 32 个字符。因为我们所卖的每种类型咖啡都使用不同的名字,名字可用于作为唯一识别咖啡的标识,因此可用于作主键。第二个列叫 SUP_ID,用于保存咖啡供应商标识;其 SQL 数据类型为 INTEGER。第 3 列叫 PRICE,因为它需要保存带小数的十进制数,因此它的 SQL 类型为 FLOAT。(注意,通常钱的 SQL 类型为 DECIMAL 或 NUMERIC,但在不同 DBMSs 间存在差异,为了避免于老版本的 JDBC 的不兼容性在本教程我们采用更标准的 FLOAT 类型)SALES 列的 SQL 类型为 INTEGER,其值为本星期所卖咖啡的磅数。最后一列,TOTAL 的 SQL 类型为 INTEGER,保存了迄今为止所卖咖啡的总磅数。 数据库里的第二个表 SUPPLIERS,保存了每个供应商的信息: SUP_ID SUP_NAME STREET CITY STATE ZIP 101 Acme, Inc. 99 Market Street Groundsville CA 95199 49 Superior Coffee 1 Party Place Mendocino CA 95460 150 The High Ground 100 Coffee Lane Meadows CA 93966 COFFEES 跟 SUPPLIERS 都包含列 SUP_ID,它意味着可以用 SELECT 语句从这两张表中取得有关信息。列 SUP_ID 是 SUPPLIERS 表的主键,用于唯一识别每个咖啡供应商。在 COFFEES 表中,SUP_ID 列被称外键。注意每个 SUP_ID 值在 SUPPLIERS 表里只出现一次;这对主键是必须的。在 COFFEES 表里,它作为外键,显然它可以有重复的 SUP_ID 值,因为同一供应商可以提供很多种的咖啡。在本节的最后,你将看见如何在 SELECT 语句中使用主键及外键的一个例子。 下面的 SQL 语句用于创建 COFFEES 表。列由列名跟空格跟 SQL 类型组成。列(包括列名及其 SQL 类型)跟下一个之间用逗号分隔。VARCHAR 类型创建定义了最大长度, 因此它需要有一个参数来表示最大长度。参数必须在类型后面的括号内。SQL 语句如下,列 COF_NAME 的长度 被限定为不得超过 32 个字符: CREATE TABLE COFFEES (COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, SALES INTEGER, TOTAL INTEGER) 这些代码不带 DBMS 语句结束符, 因为每个 DBMS 都可能不同。例如, Oracle 使用一个分号 (;) 作为语句的结束,而 Sybase 使用 go。你所使用的驱动程序会自动提供合适的语句结束符,因此你无须把它包括在你的 JDBC 代码中。 另外,我们应该指出的的是 SQL 语句的格式。在 CREATE TABLE 语句中,关键字采用大写字符,并且每个项目都另起一行。SQL 并没有此要求;仅仅是为了更容易阅读。SQL 标准是不区分关键词的大小写的, 因此,如下例中的 SELECT 语句可以有多种写法。因此下面两个不同写法的语句对 SQL 来说是一样的。 SELECT First_Name, Last_Name FROM Employees WHERE Last_Name LIKE "Washington" select First_Name, Last_Name from Employees where Last_Name like "Washington" 然而,引号里的内容是区分大小写的:在名字"Washington" 里 "W" 必须被大写,并且余下的字符必须是小写的。 对于标识,不同的 DBMS 有不同的要求,例如, 某些 DBMSs 要求那些列名及表名必须跟创建时的一样,有些则没有此要求。为安全起见,我们全部使用大写标识如 COFFEES、SUPPLIERS,因为我们是那样定义他们的。 到止我们写了创建 COFFEES 表的 SQL 语句。现在我们在它外面加上引号(使它成为字符串),并且字符串赋值给变量 createTableCoffees,在以后的 JDBC 代码中我们可以使用此变量。正如看到的,DBMS 并不在意分行,但对 Java 语言来,String 对象分行是通不过编译的。因而,我们可以用加号 (+) 把每一行的串连接。 String createTableCoffees = "CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)"; 我们在 CREATE TABLE 语句中使用的数据类型是通用的 SQL 类型(也称 JDBC 类型)它们在类 java.sql.Types 中定义。DBMSs 通常使用这些标准的类型,因此,当你要尝试一些 JDBC 应用程序时,你可以直接使用 CreateCoffees.java 应用程序,它使用了 CREATE TABLE 语句。如果你的 DBMS 使用了它的自己的本地的类型名字,我们为你供应其它的应用程序,我们将在后面详细解释。 在运用任何应用程序前,当然,我们将让你了解 JDBC 的基础。 创建 JDBC Statements 对象 Statement 对象用于把 SQL 语句发送到 DBMS 。你只须简单地创建一个 Statement 对象并且然后执行它,使用适当的方法执行你发送的 SQL 语句。对 SELECT 语句来说,可以使用 executeQuery。要创建或修改表的语句,使用的方法是 executeUpdate。 需要一个活跃的连接的来创建 Statement 对象的实例。在下面的例子中,我们使用我们的 Connection 对象 con 创建 Statement 对象 stmt: Statement stmt = con.createStatement(); 到此 stmt 已经存在了,但它还没有把 SQL 语句传递到 DBMS。我们需要提供 SQL 语句作为参数提供给我们使用的 Statement 的方法。例如,在下面的代码段里,我们使用上面例子中的 SQL 语句作为 executeUpdate 的参数: stmt.executeUpdate("CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)"); 因为我们已经把 SQL 语句赋给了 createTableCoffees 变量,我们可以如下方式书写代码: stmt.executeUpdate(createTableCoffees); 执行语句 我们使用 executeUpdate 方法是因为在 createTableCoffees 中的 SQL 语句是 DDL (数据定义语言)语句。创建表,改变表,删除表都是 DDL 语句的例子,要用 executeUpdate 方法来执行。你也可以从它的名字里看出,方法 executeUpdate 也被用于执行更新表 SQL 语句。实际上,相对于创建表来说,executeUpdate 用于更新表的时间更多,因为表只需要创建一次,但经常被更新。 被使用最多的执行 SQL 语句的方法是 executeQuery。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。马上你将看到如何使用这个方法。 在表中输入数据 我们已经显示了如何通过指定列名、数据类型来创建表 COFFEES,但是这仅仅建立表的结构。表还没有任何数据。我们将次输入一行数据到表中,提供每列的信息,注意插入的数据显示顺序跟表创建时候是一样的,既缺省顺序。 下列代码插入一个行数据,COF_NAME 的值为 Colombian,SUP_ID 为 101,PRICE 为 7.99,SALES 0,TOTAL 0。就象创建 COFFEES 表一样,我们创建一 Statement 对象,并执行 executeUpdate 方法。 因为 SQL 语句一行显示不下,因此我们把它分为两行,并用加号 (+) 相连。特别要注意的是,在 COFFEES 和 VALUES 之间要有空格。这个空格必须在引号之内并且要在 COFFEES 跟 VALUES 之间;没有这个空格,SQL 语句将被错误地被读作为 "INSERT INTO COFFEESVALUES ...",并且 DBMS 将寻找表 COFFEESVALUES。还要注意的是在 coffee name 上我们使用了单引号。 Statement stmt = con.createStatement(); stmt.executeUpdate( "INSERT INTO COFFEES " + "VALUES ('Colombian', 101, 7.99, 0, 0)"); 下面的代码把第二行插入到表 COFFEES 中。我们可以在使用 Statement 对象而无须为每次执行创建一个新的。 stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast', 49, 8.99, 0, 0)"); 剩下行的数据如下: stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Espresso', 150, 9.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)"); 从表中取得数据 既然表 COFFEES 中已经有数据了,我们就可以写一个 SELECT 语句来取得这些值。下面的 SQL 语句中星号 (*) 表示选择所有的列。因为没有用 WHERE 子句来限制所选的行,因此下面的 SQL 语句选择的是整个表。 SELECT * FROM COFFEES 结果是整个表的数据,如下: COF_NAME SUP_ID PRICE SALES TOTAL --------------- ------ ----- ----- ----- Colombian 101 7.99 0 0 French_Roast 49 8.99 0 0 Espresso 150 9.99 0 0 Colombian_Decaf 101 8.99 0 0 French_Roast_Decaf 49 9.99 0 0 如果你直接在数据库系统里输入 SQL 查询语句,你将在你的终端上看到如上的结果。当我们通过一个 Java 应用程序存取一个数据库时,正如我们马上要做的一样,我们需要检索结果以便我们能使用他们。你将在下一节看到如何实现。 这是 SELECT 语句的另一个例子,这将得到咖啡及其各自每磅单价的列表。 SELECT COF_NAME, PRICE FROM COFFEES 查询的结果集将具有如下形式: COF_NAME PRICE -------- ---------- ----- Colombian 7.99 French_Roast 8.99 Espresso 9.99 Colombian_Decaf 8.99 French_Roast_Decaf 9.99 上面 SELECT 语句取得了所有咖啡的名字及价格。而下面的 SELECT 语句限制那些每磅价格低于 $9.00 的咖啡才被选择。 SELECT COF_NAME, PRICE FROM COFFEES WHERE PRICE < 9.00 结果集将具有如下形式: COF_NAME PRICE -------- ------- ----- Colombian 7.99 French_Roast 8.99 Colombian Decaf 8.99 |
上一页 [1] [2] [3]
一、几种装载JDBC驱动程序的方法1. 在DriverManager中注册 举例:在DriverManager中注册Oracle JDBC Driver // 注册Oracle JDBC 驱动器 DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); 2. 直接装载 二、常见问题在WebLogic 6.x中连接Oracle 9i数据库时,可能会出现类似如下错误: java.sql.SQLException: ORA-00600: 内部错误代码,参数: [ttcgcshnd-1], [0], [], [], [], [], [],[] 示例代码:
原因分析:在WebLogic的核心包weblogic.jar($WEBLOGIC/lib)中内置了Oracle8i的驱动器,这个错误就是由于使用了Oracle8i的驱动器访问Oracle9i造成的。 解决办法:将Oracle9i的JDBC Driver(如果你安装了Oracle9i的服务器或客户端,在$ORACLE/ora90/jdbc/lib下就包含了classes12.zip或者classes12.jar)加入到你的WebLogic当前域的启动脚本(startWebLogic.cmd)中。特别注意,这个.jar一定要位于weblogic.jar之前! 版声说明:本文仅授权JavaResearch.org发表,严禁其它网站、媒体转载。 |
jdbc程序的性能主要由两个因素决定,一是数据库本身的性质,另一个是与数据库相对独立的jdbc应用程序接口(api)的使用.这里说的是如何正确使用jdbc编程接口,以获得更好的性能. jdbc主要优化有: 1.选择正确的jdbc驱动程序 2.Connention的优化 使用连接池来管理Connection对象 3.Statement的优化 使用批量更新等 4.Result的优化 正确的从数据库中get数据等 (1)选择正确的jdbc驱动程序: 1 jdbc-odbc 桥 2 本地api-部分 java驱动 3 jdbc网路协议-纯java驱动 4 jdbc本地协议 最好选择 jdbc网路协议-纯java驱动 效率比较高 但需要第三方软件的支持 比如corba weblogic属于这种类型 (2)优化Connection对象: 1.设置适当的参数 DriverManager.getConnection(String url,Properties props); 例如: Properties props=new Properties(); props.put("user","wuwei"); props.put("password","wuwei"); props.put("defaultRowPrefectch","30"); props.put("dufaultBatchValue","5"); Connection con=DriverManager.getConnection("jdbcracle:thin:@hostsString",props); 对象可以通过设置setDefaultRowPrefetch(int) 和 setDefaultBatchValue(int) 两个参数类优化连接 2.使用连接池 可以自己写一个连接池 这样程序的灵活性强,便于移植. apache项目开发了一套非常通用而表现非常稳定的对象池 http://jakarta.apache.org/commons/pool.htm 设计了自己的连接池后 在客户端调用建立对象 public Object makeObject() throws Exception{ Class.forName("oracle.jdbc.driver.OracalDriver"); return DriverManager.getConnection("url","username","password"); } 销毁对象时用 public void destroyObject(Object obj) throws Exception{ ((Connection)obj.close()); } 注意几点 对象池里有没有回收机制,对象池里有机有容量限制,对象池里有多少个闲置对象(可以释放) 3.控制事务的提交 最好手动提交事务,不但可以可以保证数据原子性,而且对新能提高留下余地. try{ connection.setAutoCommint(false); // 代码 用PreparedStatement 性能比Statementh好. connection.commit(); connection.setAutoCommit(true); } catch(SQLException e){ } finally{ //代码 if(connection!=null){ connection.close(); } } 4.适当的选择事务的隔离级别 TRANSACTION_READ_UNCOMMITED 性能最高 TRANSACTION_READ_COMMITED 快 TRANSACTION_REFEATABLE_READ 中等 RANSACTION_SERIALIZABLE 慢 (3)Statement 优化 jdbc3个接口用来处理sql的执行,是Statement PreparedStatement CallableStatement 提供适当的Statement接口 批量执行sql 从数据库批量获取数据 PreparedStatement 比Statement性能要好 主要体现在一个sql语句多次重复执行的情况 PreparedStatemnt只编译解析一次而Statement每次编译一次. 批量修改数据库 Statement 提供了方法addBatch(String)和executeBatch() 调用方法为stmt.addBatch("isnert....."); stmt.addBatch("update.....") stmt.executeBatch(); 也可以用PreparedStatement从而更好的提高性能. pstmt=conn.preparedStatement("insert into test_table(......) values(....?)"); pstmt.setString(1,"aaa"); pstmt.addBatch(); pstmt.setString(1,"bbb"); pstmt.addBatch(); ..... pstmt.executeBatch(); 批量地从数据库中取数据. 通过setFetchSize()和getFectchSize()方法来设定和查看这个参数.这个参数对体统的性能影响比较大. 这个参数太小会严重地降低程序地性能. Connection Statement ResultSet都有这个参数,他们对性能地影响顺序是: ResultSet---------Statement---------Connection (4)优化ResultSet. 体现在以下几个方面 批量读取数据.合理设置ResultSet的getFetchSize()和setFetchSize()方法中的参数 使用正确的get和set方法 使用整数而不是字段名作为参数性能比较高, 例如 setInt(1,100); setString(2,"aaaa"); 比 setInt("id","100"); setString("name","aaaa"); 性能好 设置适当的滚动方向.有3个方向FETCH_FORWORD,FETCH_REVERSE FETCH_UNKNOWN 单向滚动性能比较高. 其他方面的性能优化 及时显示的关闭Connection Statement ResultSet 其中Connection可以用Connetion Pool处理. 使用数据库系统的强大查询功能去组织数据.这样程序运行是和数据库服务的交互次数少,数据库返回给 程序的记录条数少的多,所以性能有很大的提高. 作者不清
|