java.sql
Main JDBC classes:
jdbc:odbc:oracle --> to access ODBC data source jdbc:oracle:thin:@oracleserver:1521:oracle9i --> to access Oracle using thin driver
Driver type | Explanation | Comment |
---|---|---|
1 | The JDBC/ODBC bridge driver | A piece of native C-code that translates a JDBC call to an ODBC call. Use this driver for development, not for industrial-strength application environments. Note that you have to have an ODBC database driver manager + an ODBC database driver installed on the server in addition to the JDBC/ODBC bridge. |
2 | Native API partly java driver | A piece of native C-code that translates a java JDBC call to a native database call level API. Use this driver for development and deployment. Due to its native code, this driver can only be used by Java Applications with full computer access (i.e. not Applets). |
3 | JDBC-Net pure Java driver | A piece of pure java code that translates an incoming JDBC call to an outgoing database Net protocol call (such as SQL*Net). Use this driver for development and deployment. Flexible and powerful, This driver can be used by any Java component and requires only connect access to work. |
4 | Native protocol pure Java driver | A piece of pure java code that translates an incoming JDBC call to an outgoing database native protocol call (such as Oracle CLI). Use this driver for development and deployment. This driver type is the recommended one for server-side java development. |
PreparedStatement
class is the ability to create an incomplete query and supply parameter values at execution time.
Quite often in database processing, we come across the situation wherein one transaction can change a value, and a second transaction can read this value before the original change has been committed or rolled back. This is known as a dirty read scenario because there is always the possibility that the first transaction may rollback the change, resulting in the second transaction having read an invalid value.
While you can easily command a database to disallow dirty reads, this usually degrades the performance of your application due to the increased locking overhead. Disallowing dirty reads also leads to decreased system concurrency.
// Prepare a Statement: PreparedStatement stmnt = conn.prepareStatement("select aBlob from BlobTable"); // Execute ResultSet rs = stmnt.executeQuery(); while(rs.next()) { try { // Get as a BLOB Blob aBlob = rs.getBlob(1); byte[] allBytesInBlob = aBlob.getBytes(1, (int) aBlob.length()); } catch(Exception ex) { } } }
ResultSet result = stmt.executeQuery("..."); List list = new LinkedList(); while(result.next()) { list.add(result.getString("col")); }If there are multiple columns in the result set, you'll have to combine them into their own data structure for each row. Arrays work well for that as you know the size, though a custom class might be best so you can convert the contents to the proper type when extracting from database, instead of later.
rs.getString("email"); if ( rs.wasNull() ) // no email else // use email
Statement stmt = con.createStatement(); stmt.setFetchSize(100); ResultSet rs = stmt.executeQuery("select * from customers");
You can also control the direction in which the rows are processed. For instance:
stmt.setFetchDirection(ResultSet.FETCH_REVERSE)will process the rows from bottom up.The driver manager usually defaults to the most efficient fetch size so you may try experimenting with different value for optimal performance.
try { dbCon.setAutoCommit(false); Statement stmt= dbCon.createStatement(); stmt.addBatch("INSERT INTO bugs VALUES (...)"); stmt.addBatch("INSERT INTO bugs VALUES (...)"); int[] updCnt = stmt.executeBatch(); dbCon.commit(); } catch (BatchUpdateException be) { //handle batch update exception int[] counts = be.getUpdateCounts(); for (int i=0; i < counts.length; i++) { System.out.println("Statement["+ i + "] :" + counts[i]); } dbCon.rollback(); } catch (SQLException e) { //handle SQL exception dbCon.rollback(); }
You can retrieve, store and update SQL3 types using the corresponding getXXX(), setXXX(), and updateXXX() methods defined in ResultSet interface.
You may create a digitally signed applet using a Certificate to circumvent the security sandbox of the browser.
The Statement.execute() method helps in these cases. Method Statement.execute() returns a boolean to tell you the type of response : true indicates next result is a ResultSet then use Statement.getResultSet() to get the ResultSet, false indicates result is an update count then use Statement.getUpdateCount() to get the update count.
After processing each response, you use Statement.getMoreResults() to check for more results, again returning a boolean.
The following demonstrates the processing of multiple result sets:
boolean result = stmt.execute(" ... "); int updateCount = stmt.getUpdateCount(); while (result || (updateCount != -1)) { if(result) { ResultSet r = stmt.getResultSet(); // process result set } else if(updateCount != -1) { // process update count } result = stmt.getMoreResults(); updateCount = stmt.getUpdateCount(); }
CallableStatement cs = con.prepareCall("{? = call procedure(?,?) }"); cs.registerOutParameter(1, java.sql.Types.VARCHAR ); cs.setInt(2, value1 ); cs.setInt(3, value2 ); ResultSet lrsReturn = null; lrsReturn = msProcedure.executeQuery(); while( lrsReturn.next() ) { System.out.println("Got from result set: " + lrsReturn.getInt(1)); } System.out.println( "Got from stored procedure: " + cs.getString( 1 ) );
USERID FIRST_NAME LAST_NAME abc a b xyz x y
Since Excel comes with an ODBC driver, we'll use the JDBC-ODBC bridge driver that comes packaged with Sun's JDK to connect to our spreadsheet.
In Excel, the name of the worksheet is the equivalent of the database table name, while the header names found on the first row of the worksheet is the equivalent of the table field names. Therefore, when accessing Excel via jdbc, it is very important to place your data with the headers starting at row 1.
Connection conn=null; Statement stmt=null; String sql=""; ResultSet rs=null; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conn=DriverManager.getConnection("jdbc:odbc:excel","",""); stmt=conn.createStatement(); sql="select * from [Sheet1$]"; rs=stmt.executeQuery(sql); while(rs.next()) { System.out.println(rs.getString("USERID")+ " "+ rs.getString("FIRST_NAME")+" "+ rs.getString("LAST_NAME")); } } catch (Exception e) { System.err.println(e); } finally { try { rs.close(); stmt.close(); conn.close(); } catch(Exception e){} }
The only significant difference is in the SELECT statement. Although your data is residing in the worksheet called "Sheet1", you'll have to refer to the sheet as Sheet1$ in your SQL statements. And because the dollar sign symbol is a reserved character in SQL, you'll have to encapsulate the word Sheet1$ in brackets, as shown in the code.
com.foo.dbBean bean = new com.foo.dbBean(); //call setters to initialize bean req.setAttribute("dbBean", bean); url="..."; //relative url for display jsp page ServletContext sc = getServletContext(); RequestDispatcher rd = sc.getRequestDispatcher(url); rd.forward(req, res);The bean can then be accessed within the JSP page via the useBean tag as:
<jsp:useBean id="dbBean" class="com.foo.dbBean" scope="request"/> ... <% //iterate through the rows within dbBean and //access the values using a scriptlet %>Also, it is best to design your application such that you avoid placing beans into the session unless absolutely necessary. Placing large objects within the session imposes a heavy burden on the performance of the servlet engine.
The code snippet to retrieve the OUT and INOUT parameters is as follows:
CallableStatement cs = connection.prepareCall( "(CALL MultiSP(?, ?, ?))" ); cs.setInt(1, 1); // set the IN parm I1 to 1 cs.setInt(3, 3); // set the INOUT parm IO1 to 3 cs.registerOutParameter(2, Types.INTEGER); // register the OUT parm O1 cs.registerOutParameter(3, Types.INTEGER); // register the INOUT parm IO1 cs.execute(); int iParm2 = cs.getInt(2); int iParm3 = cs.getInt(3); cs.close();The code really is just additive; be sure that for each IN parameter that setXXX() is called and that for each INOUT and OUT parameter that registerOutParameter() is called.
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);Now use the Statement object to execute the query: For example:
ResultSet srs = stmt.executeQuery("SELECT FIRST_NAME, AGE FROM STUDENTS_TABLE");
Statement stmt = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE );Note that the spec allows a driver to return a different type of Statement/ResultSet than that requested, depending on capabilities and circumstances, so the actual type returned should be checked with ResultSet.getConcurrency().
// loads the JDBC driver Class.forName("org.gjt.mm.mysql.Driver").newInstance(); // get a database connection Connection conn = DriverManager.getConnection("jdbc:mysql://hostname/databaseName", "user","password");
setMaxRows(int) sets the limit of the maximum number of rows in a ResultSet object. If this limit is exceeded, the excess rows are "silently dropped". That's all the API says, so the setMaxRows() method may not help performance at all other than to decrease memory usage. A value of 0 (default) means no limit.
Some downsides are:
javax.servlet.ServletException : oracle.jdbc.driver.OracleDriver Root Cause : java.lang.ClassNotFoundException: oracle:jdbc:driver:OracleDriverBut, the Oracle JDBC driver ZIP file (classes111.zip)is available in the system classpath.
The problem can be solved by using the following procedure:
public void setNull(int parameterIndex, int sqlType) throws SQLException
For Arrays, use the various forms of getArray() and getResultSet().
For Blobs, use getBinaryStream() or getBytes(long pos, int length).
For Clobs, use getAsciiStream() or getCharacterStream().