Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Concurrency control wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Versant Object Database wikipedia , lookup
Database model wikipedia , lookup
Relational model wikipedia , lookup
JDBC API Polyhedra Ltd Copyright notice This document is copyright © 1994 - 2006 by Polyhedra Ltd. All Rights Reserved. This document contains information proprietary to Polyhedra Ltd. It is supplied in confidence and must not be used for any purpose other than that for which it was supplied. This document may not, in whole or in part, be copied, photocopied, reproduced, translated or reduced to any electronic medium or machine readable form without prior written consent from Polyhedra Ltd. Trademarks Polyhedra is a registered trademark of Polyhedra Ltd. Certain terms used in this document are trademarks; while these are not acknowledged as such in the text, this should in no way be construed as a challenge to that trademark status, or as an infringement of that status. Manual Details Manual title JDBC API Document number manuals/jdbc Revision number 6.3.0 Revision Date 22nd June 2006 Software Version This documentation corresponds to the following version of the software: Version 6.3 i PREFACE This document describes the Java Database Connectivity Application Programming Interface, (JDBC API) component of Polyhedra. Its purpose is to provide a summary of the features of the JDBC API and to outline how the JDBC API can be configured and executed. The JDBC API is designed for use by application writers and it is therefore assumed that the reader is familiar with the process of writing client applications. Most readers will find it beneficial to have read the Polyhedra Overview and the Polyhedra User's Guide documents first. iii CONTENTS 1. INTRODUCTION.......................................................................................................................... 7 2. JDBC ARCHITECTURE.............................................................................................................. 8 2.1 2.2 2.3 2.4 3. CONNECTION. ........................................................................................................................... 10 3.1 3.2 3.3 3.4 3.5 4. OPENING A CONNECTION ......................................................................................................... 10 SENDING SQL STATEMENTS ................................................................................................... 11 TRANSACTIONS ....................................................................................................................... 13 ISOLATION LEVELS .................................................................................................................. 13 RESOURCE MANAGEMENT....................................................................................................... 13 STATEMENTS ............................................................................................................................ 14 4.1 4.2 4.3 4.4 4.5 4.6 5. PURPOSE OF THE API ................................................................................................................ 8 TWO AND THREE TIER MODELS ................................................................................................ 8 SQL CONFORMANCE ................................................................................................................ 9 DRIVER TYPE ............................................................................................................................ 9 CREATING STATEMENT OBJECTS ............................................................................................. 14 EXECUTING STATEMENTS USING STATEMENT OBJECTS ........................................................... 14 STATEMENT COMPLETION ....................................................................................................... 15 CLOSING STATEMENTS ............................................................................................................ 15 SQL ESCAPE SYNTAX STATEMENTS ........................................................................................ 15 SENDING BATCH UPDATES ....................................................................................................... 16 RESULT SETS............................................................................................................................. 17 5.1 ROWS AND COLUMNS .............................................................................................................. 17 5.2 CURSORS ................................................................................................................................ 17 5.2.1 Cursor movement examples ........................................................................................... 18 5.3 DETERMINING THE NUMBER OF ROWS IN A RESULT SET .......................................................... 19 5.4 RETRIEVING COLUMN VALUES ................................................................................................ 19 5.5 TYPES OF RESULT SETS........................................................................................................... 20 5.6 CONCURRENCY ....................................................................................................................... 20 5.7 USING PREPARED STATEMENT TO CREATE RESULT SETS ........................................................ 21 5.8 USING UPDATEXXX METHODS ............................................................................................... 21 5.9 ROW DELETION ....................................................................................................................... 22 5.10 ROW INSERTION ...................................................................................................................... 22 5.11 QUERIES THAT PRODUCE UPDATABLE RESULTS ....................................................................... 23 5.12 CLOSING A RESULT SET .......................................................................................................... 23 6. PREPARED STATEMENT ........................................................................................................ 24 6.1 6.2 6.3 6.4 6.5 6.6 6.7 7. CREATING PREPAREDSTATEMENT OBJECTS ............................................................................ 24 PASSING IN PARAMETERS ...................................................................................................... 24 DATA TYPE CONFORMANCE ON IN PARAMETERS .................................................................. 25 USING SETOBJECT................................................................................................................... 25 SENDING JDBC NULL AS AN IN PARAMETER ........................................................................ 26 SENDING VERY LARGE IN PARAMETERS.................................................................................. 26 USING PREPAREDSTATEMENT OBJECTS IN BATCH UPDATES .................................................. 26 MAPPING SQL TYPES TO JAVA TYPES.............................................................................. 27 7.1 MAPPING SQL TYPES TO JAVA TYPES .................................................................................... 27 v CONTENTS JDBC API 7.2 BASIC JDBC TYPES ................................................................................................................ 27 7.2.1 binary ............................................................................................................................. 27 7.2.2 bool ................................................................................................................................ 28 7.2.3 char ................................................................................................................................ 28 7.2.4 datetime.......................................................................................................................... 29 7.2.5 float ................................................................................................................................ 29 7.2.6 integer ............................................................................................................................ 29 7.3 DYNAMIC DATA ACCESS ........................................................................................................ 29 vi JDBC API CONTENTS 1. Introduction This manual describes the Polyhedra Java Database Connectivity Application Programming Interface (JDBC API). The Polyhedra JDBC API is a Java programming language interface designed for executing SQL statements. It consists of a set of classes and interfaces written in the Java Programming language that uses the native protocol of the Polyhedra database. The JDBC provides a standard API for database developers making it possible to write Polyhedra client applications using a pure Java API. The Polyhedra JDBC API supports the following interfaces: • • • • • • • Driver Connection Statement PerparedStatement ResultSet ResultSetMetaData DatabaseMetaData The JDBC driver supports all SQL standards and all features of Polyhedra, including Active Queries 7 CONTENTS JDBC API 2. JDBC architecture The Polyhedra JDBC API is intended for use by application writers, who wish to write Java client applications to communicate with a Polyhedra server. The JDBC driver is a type 4 driver, which uses the Polyhedra Native Protocol over TCP/IP to communicate with the Polyhedra Database Server. The JDBC Driver is written in pure Java and uses only the standard Java API. It is designed to run on Java version 1.2 and later and should be compatible with Java 1.1.X. The Driver supports JDBC 2.0 with some limitations. 2.1 Purpose of the API The Polyhedra JDBC API is a low-level interface between Polyhedra client/server applications. It is used to invoke (or "call") SQL commands directly allowing the client application to: • Establish a connection with a Polyhedra database server or other client application • Send SQL statements • Process the results 2.2 Two and Three Tier models The JDBC API supports both Two and Three Tier models for database access. Figure 1 illustrates a two-tier model for database access. Java Application JDBC Polyhedra RTRDB Figure 1 - Two-Tier Model for Database Access In a Two-Tier model, a Java application communicates directly with the data source in a client /server relationship. This requires a JDBC driver capable of communicating with the particular data source being accessed. User's command statements are sent via the JDBC to the database and the results of these statements are returned to the user. 8 JDBC API CONTENTS In a Three-Tier model, commands are sent from the Client application via an additional Client based server to the data source. The data source processes the commands and sends results back to the Client application server, which forwards them back to the Client application. This configuration is illustrated in Figure 2. Client Application Client Application Server JDBC RTRBD Figure 2 - Three-Tier Model for Database Access 2.3 SQL Conformance The JDBC API supports the following SQL standards: • ANSI SQL-92 The JDBC permits SQL queries to be passed direct to the RTRDB with no pre-processing by the driver. This allows the application to use the required amount of SQL functionality to satisfy the query. The JDBC also allows standard ODBC style escape clauses. The escape syntax provides a standard JDBC syntax for some of the more common areas of SQL standard variations. For more complex applications the Polyhedra JDBC API provides descriptive information about the RTRDB by using an interface DatabaseMetaData, this allows applications to adapt to the specific requirements and individual capabilities of each RTRDB. 2.4 Driver Type The JDBC API uses a Class 4 pure Java driver. This driver converts JDBC calls directly into the required Polyhedra protocol to permit communication with any Java client application. The driver type is specified at connection by the client application at the beginning of the connection statement. 9 CONTENTS JDBC API 3. Connection. A Connection object represents a connection with a Polyhedra Real Time Relational Database, (RTRDB). A connection session includes the required SQL statements that are executed by the Client application and the results that are returned by the database during that connection. A client can have and unspecified number of connections with a particular database. A user can obtain information about a connection object's database application by invoking the Connection.getMetaData method. This method returns a DatabaseMetaData object that holds information about the database's tables, the SQL grammar it supports, its stored procedures, the capabilities of this connection, etc. 3.1 Opening a connection To initiate a connection users call Driver methods directly. The fully qualified driver name is "com.polyhedra.jdbc.JdbcDriver". The driver URL has the following format: jdbc:polyhedra://<service>,<service>,...[[<options>]] where <service> has the format, [[<host>]:][<port>] and the connection options <options> are described in the manual Polyhedra User’s Guide. The host name is optional and may be expressed as an IP address - i.e. 123.0.0.1 Default is ' localhost', which is normally set to IP address 127.0.0.1 For example: "jdbc:polyhedra://localhost:8000 The "8000" specifies the TCP/IP port number used by the RTRDB. It is in the form of nnnn where 'n' s specify the required digits to make a connection The supported connection properties are as follows: + user - polyhedra user name + password - user password + environment - polyhedra environment (for Notify Client Type) + safe.commit – enable safe-commit mode (default false) + ft.enable – enable fault tolerance mode (default false) 10 JDBC API CONTENTS + reconnect.retries – number of times to attempt to connect to each service during fail-over (default 1) + reconnect.timeout – time-out period associated with an attempt to connect to each service during fail-over in milliseconds (default 5000) + reconnect.interval – interval between each attempt to connect to a service during fail-over in milliseconds (default 5000) + heartbeat.timeout – time-out period associated with each heartbeat message. Absence of a reply to a heartbeat message before this period has elapsed will result in a client assuming the RTRDB has failed and instigating its fail-over procedure (default 5000) + heartbeat.interval – interval between heartbeat messages sent from the client to the RTRDB in milliseconds (default 5000) The connection properties can also be specified with the URL by appending a semicolon (;) by name=value pairs, separated by semicolons. followed For example: jdbc:polyhedra://:8000;user=employee no; password=bright jdbc:polyhedra://8000,8001[rw];ft.enable=yes;reconnect.retries=10 3.2 Sending SQL statements Once a connection is established, it is used to send SQL statements to the database. The JDBC API does not restrict the types of SQL statements that have been sent; this provides added flexibility allowing the use of application specific statements or possibly non-SQL statements. The user is responsible for ensuring that the database is capable of processing the required SQL statement being sent. If the database does not support the required type of SQL statement then it will return an exception. The Polyhedra JDBC API provides two interfaces for sending SQL statements to the database and corresponding methods in the connection interface create instances of them. The interfaces for sending SQL statements and the connection methods that create them are detailed as follows: Statement Created by the connection.createstatement methods. A Statement object is used for sending SQL statements with no parameters. PreparedStatement Created by the Connection.prepareStatement methods. A PreparedStatement object is used for precompiled SQL statements. These can take one or more parameters as input arguments (IN parameters). PreparedStatement has a group of methods that set the value of IN parameters, which are sent to the database when the statement is executed. PreparedStatement extends Statement and therefore includes Statement methods. A PreparedStatement object has the potential to be more 11 CONTENTS JDBC API efficient than a Statement object because it has been precompiled and stored for future use. Therefore, in order to improve performance, a PreparedStatement object is sometimes used for an SQL statement that is executed many times. The following list provides a reference to help determine which connection method is appropriate for creating different types of SQL statements: • createstatement methods -used for simple SQL statements with no parameters • prepareStatement methods - For frequently executed SQL statements It is possible to utilise these statements to create result sets that are scrollable and updateable. These statements also employ additional parameters used to specify the type of ResultSet and the concurrency level of the result set being created. 12 JDBC API CONTENTS 3.3 Transactions A transaction consists of one or more statements that have been executed completed and then either committed to the database or rolled back. Each transaction is atomic. How statements are included in transactions is dependent on the auto-commit mode. Normal processing is as follows: Single 'update' commands The processing of updates is dependent on the auto-commit mode. If auto-commit is enabled, these generate a new transaction each time the previous command is successful, and each command is atomic. If auto-commit is disabled, a new transaction is only generated by the first update after the previous transaction has been completed. Each transaction is explicitly completed by calling commit() or rollback(). Batch 'update' commands The processing of batch updates, specifically executeBatch(), is also dependent on the auto-commit mode in the same way as update commands. Queries If queries are not 'updatable' no transaction is performed. Otherwise the processing is dependent on the auto-commit mode. If auto-commit is enabled, a transaction is created for the result set at the first updateRow(), insertRow(), or deleteRow(). When the result set is closed, its transaction is automatically committed. If auto-commit is disabled, any changes are included in the current transaction. The transaction must be explicitly completed by calling commit() or rollback(). 3.4 Isolation levels The Polyhedra JDBC API supports transaction processing and manages potential conflicts that may arise when two transactions are in operation on the database at the same time by calling the TRANSACTION_SERIALIZABLE option. This option is always set to on and is returned when the user calls a getTransactionIsolation method. The getTransactionIsolation method uses the TRANSACTION_SERIALIZABLE function as its only parameter. All other values will return an SQLException. 3.5 Resource management The Polyhedra JDBC Driver will automatically close result sets, statements and connections when they are garbage-collected. However, garbage -collection may not be performed before program exit. It is therefore recommended that users close connections when they are no longer required. 13 CONTENTS JDBC API 4. Statements A Statement object is used to send SQL statements to a database. There are two types of statement objects, which act as containers for executing SQL statements on a given connection: Statement and PreparedStatement. The Statement interface provides basic methods for executing statements and retrieving results. The PreparedStatement interface adds methods for dealing with IN parameters. 4.1 Creating statement objects A Statement object is created with the connection method createstatement as follows: Connection con = DriverManager.getConnection(url, "", "") Statement stmt = con.createstatement(); The SQL statement that will be sent to the database is supplied as the argument to one of the execute methods on a Statement object. This is shown in the following statement, which uses the method executeQuery: ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2") The variable rs references a result set that cannot be updated and in which the cursor can move only forward, which is the default behaviour for ResultSet objects. The Polyhedra JDBC API supports a new version of the method Connection.createstatement that makes it possible to create Statement objects that produce result sets that are scrollable and/or updatable. 4.2 Executing statements using Statement objects The Statement interface provides three different methods for executing SQL statements: executeQuery, executeUpdate and execute. the product of the SQL statement. The correct user method is determined by executeQuery This method is designed for statements that produce a single result set, such as Select statements executeUpdate This method is used to execute INSERT, UPDATE or DELETE statements and also SQL DDL (Data Definition Language) statements such as CREATE TABLE, DROP TABLE and ALTER TABLE. The effect of an INSERT, UPDATE or DELETE statement is a modification of one or more columns in zero or more rows in a table. The return value of executeUpdate is an integer that includes the number of rows that were affected. For statements such as CREATE TABLE or DROP TABLE, which do not operate on rows, the return value of executeUpdate is always zero. execute This method is used when it is not known if the SQL statement is a SELECT or not. 14 JDBC API CONTENTS All methods for executing statements close the calling Statement objects current result set if there is one open. This means that any processing of the current ResultSet object needs to be completed before a Statement object is re-executed. The prepareStatement interfaces which inherits all of the methods in the Statement interface has its own versions of the methods executeQuery, executeUpdate and execute.Statement objects. These methods do not themselves contain an SQL statement. PreparedStatement objects do not supply an SQL statement as a parameter to these methods because they already contain a precompiled SQL statement. 4.3 Statement completion A statement is considered complete when it has been executed or when all the rows in the ResultSet object have been retrieved and when the ResultSet object is closed. For the executeQuery method, which returns one result set, the statement is complete when all the rows in the ResultSet object have been retrieved. For the executeUpdate method, a statement is complete when it is executed. If the execute method is called the statement will be complete when the result set is closed or the update count has been retrieved. 4.4 Closing statements Statement objects will be closed automatically by the Java garbage collector. However, statements should be closed explicitly when they are no longer needed. This ensures that database resources are maximised and avoids potential memory problems. 4.5 SQL escape syntax statements Statement objects may contain SQL statements that use the SQL escape syntax. Escape syntax signals the driver that the code within it should be handled differently. When escape processing is enabled (by calling Statement.setEscapeProcessing(true) or RowSet.setEscapeProcessing(true)the driver will scan for any escape syntax and translate it into code that the particular database understands. This makes escape syntax DBMS independent and allows a programmer to use features that might not otherwise be available. An escape clause is defined as follows: {keyword…..parameters…..} The following keywords are used to identify escape clauses: d - date literal t - time literal ts - timestamp literal Examples of these escape clauses are listed below: {d '2001-01-01'} {t'00:00:00'} {ts '2001-01-01 00:00:00'} {ts '2001-12-31 23:59:59.999'} 15 CONTENTS JDBC API 4.6 Sending batch updates The batch update facility in the Polyhedra JDBC API is atomic allows a Statement object to submit multiple update commands together as a single unit, or batch, to the RTRDB. The ability to submit multiple updates as a batch update rather than sending individual updates greatly improves performance in some situations. The following example illustrates a batch file update, which inserts a new row into three different tables to add a new employee to a company database. After creating the Statement object stmt, it appends three SQL INSERT INTO commands to the batch with the method addBatch and then forwards the batch to the database with the executeBatch method. The syntax is as follows: Statement stmt = con.createstatement(); stmt.addBatch("INSERT INTO employees VALUES (1000, 'Name')"); stmt.addBatch("INSERT INTO departments VALUES (260, 'Item')"); stmt.addBatch("INSERT INTO emp_dept VALUES (1000, '260')"); int [] updateCounts = stmt.executeBatch(); In the Polyhedra JDBC API all transactions concerned with batch executions are atomic. If any update statement in the batch fails all prior updates are rolled back. In the Polyhedra JDBC API a Statement object is created with an associated list of commands. This list is empty and commands are appended to the list with the Statement method addBatch. All commands added to the list must all return a simple update count. If, for example, one of the commands is a query (Select statement), which will return a result set, the method executeBatch method will throw up a BatchUpdateException. A statement object's list of commands can be deleted by invoking the method clearBatch on it. 16 JDBC API CONTENTS 5. Result Sets A ResultSet is a Java object that contains the results of executing an SQL query. Data stored in a ResultSet object is retrieved through a series of get methods that allow access to the various columns of the current row. The ResultSet.next method is used to move to the next row of the ResultSet, making it the current row. The general form of a result set is a table with column headings and the corresponding values returned by a query. For example, if your query is Select a, b, c From Table1, your result will have the following form: A _ _ _ _ _ _ _ B _ _ _ _ _ _ _ C _ _ _ _ _ _ _ 12345 77845 77965 Andrew Chris Richard 98763790.88 66357890.00 78597987.27 The following code segment is an example of executing an SQL statement that will return a collection of rows, with column a as an int, b as a string and c as a float: java.sql.Statement stmt = con.createstatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); While (rs.next()){ // retrieve and print the values for the current row int i = rs.getInt ("a"); string s = rs.getString ("b"); float f = rs.getFloat ("c"); Sytem.out.println("ROW = " + I + "" + s + "" + f); } 5.1 Rows and columns A ResultSet will appear in table form containing column values from a database table that satisfies the conditions of a specific query. If the query calls for a particular table then all of the table information will be displayed. 5.2 Cursors A ResultSet object maintains a cursor, which indicates the current row of data. The cursor movement is scrollable able to move throughout the rows within the ResultSet. The positions indicated in the table below will move the cursor backward throughout the result set table. These methods can only be used with the method TYPE_SCROLL_XXX: 17 CONTENTS JDBC API Method Description previous Moves the cursor backward through the ResultSet table first Moves the cursor to the first row of the ResultSet table last Moves the cursor to the last row of the ResultSet table absolute Moves the cursor to a particular row of the ResultSet table relative Uses current row as a reference point for movement to other rows within the table afterLast Moves the cursor to a point after the last row in the table beforeFirst Moves the cursor to a point before the first row in the table When a cursor is positioned on a particular row within the ResultSet table it designates that row as the current row. Any methods called whilst the cursor is positioned on that row will: • Operate on values within that row (method such as getXXX and updateXXX) • Operate on the row as a whole (such as updateRow, insertRow, deleteRow, refreshRow) • Use that row as a starting point for movement to other rows (such as the method relative) The cursor will remain active until the ResultSet object or its parent Statement object is closed. 5.2.1 Cursor movement examples beforeFirst Positions the cursor before this first row and then iterates forward through the contents of the result set. The methods getString and getFloat retrieve the column values from each row until there are no more rows, at which time the method next returns the value false. rs.beforeFirst(); While (rs.next()) { System.out.printIn(rs.getString("EMP_NO") + " " + rs.getFloat("SALARY"); } afterLast Positions the cursor at the end of the result set and invokes the method previous within a while loop to iterate through the contents of the result set by moving to the previous row with each iteration. The method previous returns false when there are no more rows, so the loop ends after all the rows in the ResultSet have been visited. 18 JDBC API CONTENTS rs.afterLast(); While (rs.previous()) { System.out.printIn(rs.getString("EMP_NO") + " " + rs.getFloat("SALARY")); 5.3 Determining the number of rows in a result Set This option is used for determining the number of rows in scrollable result set. For a scrollable ResultSet, the cursor is placed on the last row of the ResultSet to determine the number of rows. The example that follows shows a result set which has one row for each company employee: ResultSet rs = stmt.executeQuery( "SELECT LAST_NAME, FIRST_NAME FROM EMPLOYEES"); rs.last(); int numberOfRows = rs.getRow(); System.out.printIn("COMPANY, Ltd. has " + numberOfRows + " employees"); rs.beforeFirst(); while (next()) { ... // retrieve first and last names of each employee } 5.4 Retrieving column values With scrollable result sets the column name or column number may be used to designate the column from which to retrieve data. For example, if the second column of a ResultSet object rs is named TITLE, and it stores values as strings, either of the following statements will retrieve the value stored in that column. String s =rs.getString(2); Or String s =rs.getString("TITLE"); The option of using column name was provided so that a user who specifies column names in a query can use those same names as the arguments to getXXX methods. If, however the SELECT statement does not specify column names column numbers should be used. In these instances there is no method, which allows the user to identify individual column names. In some instances there is a possibility that a result set can return results with columns that share the same names. If a column name is used as a parameter to obtain a getXXX method, getXXX will return the value of the first matching column name. Therefore, if multiple columns with the same name exist the user should use a column index method to ensure that the correct column value is retrieved. If the column name is known but not the column number then the user can use the findColumn method to ascertain the column number. Information about columns contained in a particular ResultSet is available by calling the method ResultSet.getMetaData. The ResultSet.getMetaData object returned gives the number, types and properties of its ResultSet object's columns. 19 CONTENTS JDBC API 5.5 Types of Result Sets Based on the capabilities of scrollability and sensitivity to changes, there are three types of result sets available with the Polyhedra JDBC API. The following constants, defined in the ResultSet interface, are used to specify these three types of result sets: TYPE_FORWARD_ONLY The result set is nonscrollable; Its cursor can move forward only, from top to bottom. TYPE_SCROLL_INSENSITIVE The result set is scrollable; Its cursor can move forward or backward and can be moved to a particular row or to a row whose position is relative to its current position. The result set does not show changes to the underlying database, made while it is open. The membership, order and column values of rows are fixed when the result set is created. TYPE_SCROLL_SENSITIVE The result set is scrollable; its cursor can move forward and backward and can be move to a particular row or to a row whose position is relative to its current position. The result set is sensitive to committed changes made by other clients while it is open. If the underlying column values are modified, the new values are visible, this providing a dynamic view of the underlying data. The membership and ordering of rows in the result set is fixed. 5.6 Concurrency The Polyhedra JDBC API offers two updatable capabilities, specified by the following constants in the ResultSet interface: CONCUR_READ_ONLY Indicates a result programmatically. set cannot be updated Offers the highest level of concurrency (allows the largest number of simultaneous users). When a ResultSet object with read-only concurrency needs to set a lock, it uses a read-only lock. This allows users to read data but prevents them from making changes to it. Because there is no limit to the number of read-only locks that may be held on data at one time, there is no limit to the number of concurrent users unless the server or driver imposes one. CONCUR_UPDATABLE Indicates a result set that can be updated programmatically. 20 JDBC API CONTENTS Reduces the level on concurrency. Updatable result sets may use write-only locks so that only one user at a time has access to a data item. This eliminates the possibility that two or more users might change the same data, thus ensuring database consistency. However, the price for this consistency is a reduced level of concurrency. 5.7 Using Prepared Statement to create Result Sets As PreparedStatement objects inherit the methods defined in the Statement interface, they are also able to create ResultSet objects. The following statement shows the creation of a ResultSet using a PreparedStatement object Connection.con = DriverManager.getConnection( "jdbc:polyhedra://:8000"); PreparedStatement pstmt = con.prepareStatement( "SELECT EMP_NO, SALARY FROM EMPLOYEES WHERE EMP_NO = ?", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); pstmt.setString(1, "24711852"); ResultSet rs3 = pstmt.executeQuery(); The variable rs3 contains the values from the columns EMP_NO and SALARY for the row where the value for EMP_NO is 245711852. The ResultSet object rs3 is a variable result set that contains values for the columns EMP_NO and SALARY from every row in the table EMPLOYEES. The ResultSet is scrollable, updatable, responds to data changes. 5.8 Using updateXXX methods Result sets can be updated with the use of updateXXX methods. The updateXXX methods are used in conjunction with, but before insertRow()and updateRow() methods. With updateRow methods the user navigates through the result set to the required row to be updated using the various cursor movement methods explained in section 5.2. The current values of columns within that row can be viewed using the getXXX method. To update column values the updateXXX method is used and once updated the updateRow method marks the row as updated. Database updates do not occur until the result set is closed or a commit() or rollback() function is called. 21 CONTENTS JDBC API 5.9 Row deletion The Polyhedra JDBC API supports the method deleteRow which allows a row selected by a user within a ResultSet to be deleted using only methods in the Java programming language. Unlike the updateXXX methods, which affect only a row in the result set, this method affects both the current row in the result set and the underlying row in the database. The following statements remove the first row of a ResultSet object rs and also delete the underlying row from the database, which may also be the first row of the database table. rs.first(); rs.deleteRow(); 5.10 Row insertion The JDBC API defines the concept of an insert row that allows rows to be inserted into a result set table and into the underlying database table. This is a special row, associated with the result set but not part of it, which serves as a staging area for building the row to be inserted. To access the insert row, an application calls the ResultSet method moveToInsertRow, which positions the cursor on the insert row. It then calls the appropriate updateXXX methods to add column values to the insert row. When all of the columns of the row to be inserted have been set, the application calls the method insertRow. This method adds the insert row to both the result set and the database simultaneously. The following example demonstrates these steps for inserting a row from an application written in Java script. moveToInsertRow(); updateObject(1, myArray); updateInt(2, 3857); updateString(3, "Mysteries"); insertRow(); first(); There are some areas that will require attention. Firstly, it is possible to retrieve values from the insert row using the ResultSet.getXXX methods. However, until a value has been assigned to the insert row with an updateXXX method its contents are undefined. Therefore, if a getXXX method is called after the moveToInsertRow method has been called but before an updateXXX method has been called, the value it returns will be undefined. Second, calling an updateXXX method on the insert row is different from calling it on a row in the ResultSet object. When the cursor is on a row in the result set, a call to an updateXXX method updates a value in the insert row but does not change the result set. In both cases, the updateXXX method has no effect on the underlying database. Third, calling the method insertRow, which adds the insert row to both the result set and the database, may throw an SQLexception if the number of columns updated in the insert row does not match the number of columns in the database table. Some examples of this would be: a column not been given a value by calling an updateXXX method will generate an SQLexception unless that column permits null values. An SQLexception will also be generated if a result set is missing a column unless that column permits null values. Lastly, a result set keeps track of where its cursor was positioned when the cursor moved to the insert row. As a result, a call to the method ResultSet.moveToCurrentRow will return the cursor to 22 JDBC API CONTENTS the row that was the current row immediately before the method moveToInsertRow was called. The other cursor movement methods also work from the insert row, including those that use positioning relative to the current row. 5.11 Queries that produce updatable results The list below is used by the Polyhedra JDBC API to define a set of criteria that should generally produce updatable result sets for JDBC drivers that support updatability. If queries adhere to the guidelines that follow then they will produce updatable result sets: 1. 2. 3. The query is referenced to a single table in the database. The query does not contain any join operations aggregate functions or expressions. The query selects the primary key of the referenced table. If any inserts are to be performed on the result set, an SQL query should satisfy the conditions listed above and the following additional requirements: 4. The user has read/write privileges on the table. 5. The query selects all of the non-nullable columns in the underlying table. 6. The query selects all columns that do not have a default value. Conditions 4 and 5 are necessary, as any row to be inserted into a table must contain a value for each column contained within that table unless the column supports either null or default values. If the result set on which the insertion operations are to be performed, does not contain every column that requires a value, the insertion will fail. Only result sets created by query executions are updatable, those created by methods in the DatabaseMetaData interface are not scrollable or updatable. 5.12 Closing a Result Set Result sets are closed automatically by the Statement object that generated it when that statement object is closed. However, and explicit statement method close is available to enable the user to close and release the resources held by the ResultSet object. This is necessary if several statements are being used and the automatic close function does not initiate soon enough to prevent database resource conflicts. 23 CONTENTS JDBC API 6. Prepared Statement The PreparedStatement interface inherits from Statement and differs in the following areas: 1. Instances of PreparedStatement contain an SQL statement that has been precompiled. 2. The SQL statement contained in a PreparedStatement object may have one or more IN parameters. An IN parameter is defined as a parameter whose value is not specified when the SQL statement is created. The statement contains a question mark ("?") as a placeholder for each IN parameter. This question mark is also termed as a parameter marker, and applications must set a value for each question mark in a prepared statement prior to executing the prepared statement. As PreparedStatement objects are precompiled, their execution can be faster than that of Statement objects. Consequently, an SQL statement that is executed many times is often created as a PreparedStatement object to increase efficiency. Being a subclass of Statement, PreparedStatement inherits all the functionality of Statement. In addition, it adds a set of methods that are required for setting values to be sent to the database in place of the placeholders for IN parameters. The methods execute, executeQuery and executeUpdate are also modified so they can take no argument. The Statement forms of these methods (forms that take the SQL parameter) should never be used with PreparedStatement. 6.1 Creating PreparedStatement objects As with Statement objects it is possible to create a PreparedStatement object that contains a query rather than an update statement. This is performed in order to increase the efficiency of SQL statements that are executed many times. Using the method prepareStatement, the PreparedStatement object can produce ResultSet objects that are scrollable and updatable. The following example creates a PreparedStatement object that produces a scrollable and updatable ResultSet every time it is executed: PreparedStatement pstmt2 = con.prepareStatement( "SELECT a, b, c FROM Table1", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt2.executeQuery(); The object that rs represents is a result set with all the values stored in columns a, b and c of Table1, and rs is both scrollable and updatable. 6.2 Passing IN Parameters Prior to a PerparedStatement object being executed, the value of each parameter marker/placeholder must be set. This is achieved by invoking a setXXX method, where XXX is the appropriate type for the parameter. An example statement is given below, the parameter is of type long in the Java language and the method used is setLong. The first argument to the setXXX methods relates to the ordinary position of the 24 JDBC API CONTENTS parameter to be set with numbering starting at 1. The second argument relates to the value to which the parameter is to be set. The first parameter is set to 198765432 and the second parameter is set to 100000000. pstmt.setLong(1, 198765432); pstmt.setLong(2, 100000000); Once a parameter has been established for a given statement it can be used for multiple executions of that statement until it is cleared by invoking the method clearParameters or until a new value is set. The Polyhedra JDBC API permits the parameter marker to be set with an SQL3 data type as shown below where statistics is a Blob object representing an SQLBLOB value and departments is an array object representing an SQLARRAY value. PreparedStatement pstmt = con.prepareStatement( "UPDATE Table3 SET Stats = ? Where Depts = ?"); pstmt.setBlob(1, statistics); pstmt.setArray(2, departments); 6.3 Data Type Conformance on IN Parameters The XXX in a setXXX method is a type within the Java programming language. It also implicitly specifies a JDBC type as the driver maps the Java type to its corresponding Polyhedra JDBC type and sends that type to the RTRDB. Each IN parameter maps to a JDBC type that is compatible with the Polyhedra JDBC data type expected by the RTRDB. Specific Java types are used which correspond to exact Polyhedra JDBC types expected by the RTRDB. These types are covered in Section 8 of this manual, Mapping SQL and Java Types. 6.4 Using setObject Input parameters are explicitly converted to a particular JDBC type using the method setObject. This method is capable of taking a third argument, which specifies the target JDBC type. The Polyhedra JDBC API will convert the object in the Java programming language to the specified JDBC type prior to it being forwarded to the RTRDB. If no JDBC type is given, the driver will simply map the Java object to its default JDBC type and then send it to the database. This is similar to what occurs with the regular setXXX methods. In both instances the driver maps the Java type of the value to the appropriate JDBC type prior to it being sent to the database. The difference between these methods is as follows: setXXX methods use standard mapping and setObject uses mapping to object types. The capabilities of the method setObject to accept any Java object allows an application to be generic and accept input for a parameter run time. In this situation the type of input is not known when the application is compiled. By using setObject, the application can accept any Java object type as an input and convert it to the required Polyhedra JDBC type expected by the RTRDB. 25 CONTENTS JDBC API 6.5 Sending JDBC NULL as an IN parameter The setNull method allows an application writer to send a JDBC NULL (a generic SQL NULL) value to the database as an IN parameter. A JDBC NULL will also be sent to the database when a JAVA null value is passed to a setXXX method (if it takes Java objects as arguments). The method setObject, however, may only accept a Null value if the JDBC type has been specified. 6.6 Sending very large IN parameters The methods setString and setByte are used to send large character or binary values. However, the following stream methods should be used as a more convenient method of sending large character or binary values - setCharacterstream(), setAsciiStream() and setBinaryStream(). 6.7 Using PreparedStatement Objects in Batch Updates The Polyhedra JDBC API provides the ability to send multiple updates to the RTRDB for execution as a batch. The statement method addBatch is given an SQL update statement as a parameter and is added to the Statement objects list of commands to be executed in the next batch. The interface PreparedStatement has its own version of the method addBatch, which adds a set of parameters to the batch, as shown in the example that follows: PreparedStatement pstmt = con.prepareStatement( "UPDATE Table4 SET History = ? WHERE ID = ?") pstmt.setbyte[](1, byte[]1); pstmt.setlong(2, 350985839); pstmt.addBatch (); pstmt.setbyte[](1, byte[]2); pstmt.setlong(2, 350985840); pstmt.addBatch(); int[] updateCounts = pstmt.executeBatch(); When the PreparedStatement object in pstmt is executed, it will be executed twice, once with the parameters byte[] 1 and 350985839 and a second time with the parameters byte[]2 and 350985840. If either update returns anything other than a single update count, the method executeBatch will return an exception. 26 JDBC API CONTENTS 7. Mapping SQL Types To Java Types The Polyhedra JDBC API uses the following methods to transfer data between the RTRDB and a client application written in Java: • Methods on the ResultSet class for retrieving SQL SELECT results as Java types. • Methods on the PreparedStatement class for sending Java types as SQL statement parameters. This section provides the necessary information about data types affecting various classes and interfaces used in the Polyhedra JDBC API. It also describes the generic SQL data types. 7.1 Mapping SQL Types to Java Types The Polyhedra JDBC API defines a set of generic SQL type identifiers. These types have been designed to represent the most commonly used SQL types. There is no requirement for Java types to exactly match Polyhedra JDBC types. They need only represent them with sufficient information to correctly store and retrieve parameters and recover results from SQL statements. For example a Java string object does not precisely match any of the Polyhedra JDBC char types, but provides enough information to represent char successfully. The table below defines the specific Polyhedra JDBC types and gives the equivalent SQL and Java types used: Polyhedra JDBC Type Polyhedra SQL Type Java Type binary BINARY byte[] bool BOOL boolean char CHAR, VARCHAR java.lang.String datetime DATETIME java.sql.Timestamp float FLOAT, FLOAT32 double integer INTEGER, Long INTEGER8, INTEGER16 7.2 Basic JDBC Types This section describes data types supported by the Polyhedra JDBC API. It also explains their relation to both Polyhedra SQL and types in the Java programming language. 7.2.1 binary The Polyhedra JDBC type BINARY represents a variable length BINARY value. 27 CONTENTS JDBC API It relates to the Polyhedra SQL type BINARY, and the Java type byte[]. In the Java programming language there is no distinction between different binary values. All values are expressed as byte arrays. The Polyhedra JDBC driver supports the following retrieval methods for binary values: Method Description getBytes() Returns a Polyhedra result column value as an array of bytes byte[]. This is only valid if the result column type is binary. All other types will return an SQL Exception. getBinaryStream() Return an InputStream object, which the client uses to read Polyhedra result column value as a stream of bytes. This method is only valid if the result column type is binary. All other types will return an SQL Exception. setBytes() Passes an array of bytes - byte[] to set the value of a ? placeholder. This type is only valid if the type of ? placeholder is binary. All other types will return an SQL Exception. setBinaryStream() Passes an InputStream object, which the driver uses to read the value of a ? placeholder as a stream of bytes. This method is only valid if the type of ? placeholder is binary. All other types will return an SQL Exception. updateBytes() Passes an array of bytes - byte[] to set the value of a Polyhedra result column. This is only valid if the result column type is binary. All other types will return an SQL Exception. updateBinaryStream() Passes an InputStream object, which the driver uses to read the value of a Polyhedra result column as a stream of bytes. This is only valid if the result column type is binary. All other types will return an SQL Exception. 7.2.2 bool The Polyhedra JDBC type Bool represents a true Boolean and can have only two values: true or false It relates to the Polyhedra SQL type BOOL 7.2.3 char The Polyhedra JDBC type char represents a variable length character string with no specific size limitation. It relates to the Polyhedra SQL type CHAR and VARCHAR. In the Java programming language there is no distinction between different char values. All values are expressed as string arrays. The Java string stores data in UTF-16 (UCS-2) format. If the database is configured to use the UTF-8 character set, the driver converts between UTF-8 and UTF-16 (UCS-2) format as required. The Polyhedra JDBC driver supports the following retrieval method for char values: 28 JDBC API Index Method Description getString() Returns a string representation of a Polyhedra result column value. Any type value can be converted, float, int and datetime values are converted to standard ASCII forms. bool values are converted to 0 (true) or 1 (false). binary values are converted to hexidecimal. 7.2.4 datetime The Polyhedra JDBC type datetime represents a date consisting of day, month and year and time consisting of hours, minutes seconds and microseconds. It relates to the Polyhedra SQL type DATETIME The java.sql.Timestamp is a sub class of the java.util.Date class and extends this class with the addition of a nanosecond field 7.2.5 float The Polyhedra JDBC type float represents a double precision floating point number. The Java mapping for the FLOAT type is double 7.2.6 integer The Polyhedra JDBC type integer represents a 32-bit signed number. 7.3 Dynamic Data Access The Polyhedra JDBC API provides support for fully dynamically typed data access. The methods that follow facilitate accessing those values whose data types are unknown at compile time: • ResultSet.getObject • PreparedStatement.setObject The ResultSet.getObject will retrieve a value in a ResultSet as a Java object. Object is the base class for all Java objects an instance of any Java class can be retrieved as an instance of object. Built in "Primitive" types such as boolean, char, byte and float are not instances of the class object and therefore cannot be retrieved by getObject methods. Each of these "Primitive" types has a corresponding class which serves as a wrapper and instances of these classes are themselves objects. They can be retrieved with the method Resultset.getObject. Index 29 JDBC API PreparedStatement, 7 ResultSet, 7 ResultSetMetaData, 7 Statement, 7 low-level interface, 8 native protocol, 7 Polyhedra JDBC Type, 27 binary, 27 bool, 27 char, 27 datetime, 27 float, 27 integer, 27 Polyhedra Native Protocol, 8 PreparedStatement, 11 PreparedStatement interface, 14 prepareStatement methods, 12 pure Java API, 7 Queries, 13 ResultSet, 17 retrieval methods for binary values, 28 getBinaryStream, 28 getBytes, 28 setBinaryStream, 28 setBytes, 28 updateBinaryStream, 28 updateBytes, 28 Single 'update' commands, 13 SQL Type, 27 BINARY, VARBINARY, 27 BIT, 27 CHAR, VARCHAR, 27 FLOAT, DOUBLE, 27 INTEGER, BIGINT, 27 TIMESTAMP, 27 Statement, 11 Statement interface, 14 Statement object, 14 TCP/IP, 8 transaction, 13 TRANSACTION_SERIALIZABLE function, 13 Two and Three Tier models, 8 type 4 driver, 8 types of result sets, 20 TYPE_FORWARD_ONLY, 20 TYPE_SCROLL_INSENSITIVE, 20 TYPE_SCROLL_SENSITIVE, 20 updateXXX methods, 21 addBatch, 16 ANSI SQL-92, 9 batch update, 16 Batch 'update' commands, 13 clearBatch method, 16 close, 23 Concurrency, 20 CONCUR_READ_ONLY, 20 CONCUR_UPDATABLE, 20 Connection object, 10 connection properties, 11 connection session, 10 Connection.getMetaData method., 10 createstatement methods, 12 cursor movement, 17 Cursor movement examples, 18 beforeFirst, 18 Cursor Movement Examples afterLast, 18 cursor movement methods absolute, 18 afterLast, 18 beforeFirst, 18 first, 18 last, 18 previous, 18 relative, 18 deleteRow, 22 driver name, 10 driver type, 9 driver URL, 10 dynamically typed data access, 29 escape syntax, 9 execute, 14 executeBatch method, 16 executeQuery, 14 executeUpdate, 14 initiate a connection, 10 InsertRow, 22 Java Type, 27 Boolean, 27 Byte[], 27 Double, 27 java.lang.String, 27 java.sql.Timestamp, 27 Long, 27 JDBC API, 7 Connection, 7 DatabaseMetaData, 7 Driver, 7 30