Thursday, 27 March 2014

Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional!

Make your code more readable and protect it against null pointer exceptions.


A wise man once said you are not a real Java programmer until you've dealt with a null pointer exception. Joking aside, the null reference is the source of many problems because it is often used to denote the absence of a value. Java SE 8 introduces a new class called java.util.Optional that can alleviate some of these problems.


What's possibly problematic with the following code?
String version = computer.getSoundcard().getUSB().getVersion();


What can you do to prevent unintended null pointer exceptions? You can be defensive and add checks to prevent null dereferences.

String version = "UNKNOWN";
if(computer != null){
  Soundcard soundcard = computer.getSoundcard();
  if(soundcard != null){
    USB usb = soundcard.getUSB();
    if(usb != null){
      version = usb.getVersion();
    }
  }
}

The above code will work without any issues, however it is not good to see and not readable.

We just wrote the above lines to check the null references..! is it good ?

Here is the Java 8 feature.

String version = computer?.getSoundcard()?.getUSB()?.getVersion();
In this case, the variable version will be assigned to null if computer is null, or getSoundcard() returns null, or getUSB() returns null. You don't need to write complex nested conditions to check for null.
which can be used for simple cases when a default value is needed. In the following, if the expression that uses the safe navigation operator returns null, the default value "UNKNOWN" is returned; otherwise, the available version tag is returned.
String version =  computer?.getSoundcard()?.getUSB()?.getVersion() ?: "UNKNOWN";

Thank you..!
Chandrasekhara Kota



Wednesday, 19 December 2012

What is the meaning of Deprecated ? How and When To Deprecate APIs ..!




What "Deprecated" Means

You may have heard the term, "self-deprecating humor," or humor that minimizes the speaker's importance. A deprecated class or method is like that. It is no longer important. It is so unimportant, in fact, that you should no longer use it, since it has been superseded and may cease to exist in the future.
Java provides a way to express deprecation because, as a class evolves, its API (application programming interface) inevitably changes: methods are renamed for consistency, new and better methods are added, and fields change. But such changes introduce a problem. You need to keep the old API around until developers make the transition to the new one, but you don't want them to continue programming to the old API.
The ability to deprecate a class, method, or member field solves the problem. Java supports two mechanisms for deprecation: and an annotation, (supported starting with J2SE 5.0) and a Javadoc tag (supported since 1.1). Existing calls to the old API continue to work, but the annotation causes the compiler to issue a warning when it finds references to deprecated program elements. The Javadoc tag and associated comments warn users against using the deprecated item and tell them what to use instead.

When to Deprecate

When you design an API, carefully consider whether it supersedes an old API. If it does, and you wish to encourage developers (users of the API) to migrate to the new API, then deprecate the old API. Valid reasons to deprecate an API include:
  • It is insecure, buggy, or highly inefficient
  • It is going away in a future release
  • It encourages bad coding practices
Deprecation is a reasonable choice in all these cases because it preserves "backward compatibility" while encouraging developers to change to the new API. Also, the deprecation comments help developers decide when to move to the new API, and so should briefly mention the technical reasons for deprecation.
It is not necessary to deprecate individual member fields (properties) of a deprecated class, unless of course you want to explain a specific point about a property.

How to Deprecate

Starting with J2SE 5.0, you deprecate a class, method, or field by using the @Deprecated annotation. Additionally, you can use the @deprecated Javadoc tag tell developers what to use instead.
Using the annotation causes the Java compiler to generate warnings when the deprecated class, method, or field is used. The compiler suppresses deprecation warnings if a deprecated compilation unit uses a deprecated class, method, or field. This enables you to build legacy APIs without generating warnings.
You are strongly recommended to use the Javadoc @deprecated tag with appropriate comments explaining how to use the new API. This ensures developers will have a workable migration path from the old API to the new API. For more information, see Using the @deprecated Javadoc Tag.
NOTE: The Java Language Specification requires compilers to issue warnings when classes, methods, or fields marked with the @Deprecated annotation are used. Compilers are not required by the Java Language Specification to issue warnings when classes, methods, or fields marked with the @deprecated Javadoc tag are accessed, although the Sun compilers currently do so. However, there is no guarantee that the Sun compiler will always issue such warnings.

Using the @Deprecated Annotation

J2SE 5.0 introduces a new language feature called annotations (also called metadata). One of the Java language's built-in annotations is the @Deprecated annotation. To use it, you simply precede the class, method, or member declaration with "@Deprecated."
Using the @Deprecated annotation to deprecate a class, method, or field ensures that all compilers will issue warnings when code uses that program element. In contrast, there is no guarantee that all compilers will always issue warnings based on the @deprecated Javadoc tag, though the Sun compilers currently do so. Other compilers may not issue such warnings. Thus, using the @Deprecated annotation to generate warnings is more portable that relying on the @deprecated Javadoc tag.
In addition, the @Deprecated annotation causes the javadoc-generated documentation to be marked "Deprecated" wherever that program element appears.
NOTE: Deprecation applies to classes and to individual methods or properties, not to their names. It is possible for a single method to have deprecated and non-deprecated overloadings. It is possible for a non-deprecated property to hide or override a deprecated one, which removes deprecation. As developer of an API, it is your responsibility to deprecate overrides of a deprecated method, if in fact they should be deprecated.

Example

The following is a simple example of using the @Deprecated annotation from java.lang.Thread:
public
class Thread implements Runnable {
...
@Deprecated
    public final void stop() {
  synchronized (this) {
...

Using the @deprecated Javadoc Tag

You can use the @deprecated tag to make Javadoc show a program element as deprecated. The @deprecated tag must be followed by a space or newline. In the paragraph following the @deprecated tag, explain why the item has been deprecated and suggest what to use instead.
Javadoc generates special HTML based on @deprecated tags: it moves the paragraph following the @deprecated tag to the front of the description, placing it in italics and preceding it with a warning, "Note: foo is deprecated", in bold. It also adds "Deprecated" in bold to any index entries mentioning the deprecated entity.
The tagged paragraph can be empty, but empty deprecation paragraphs are bad form, because they do not help the user fix the warnings that arise from the deprecation. Include paragraphs marked with @link or@see tags that refer to the new versions of the same functionality. It is usually not a good idea to mention a timetable for phase-out of the deprecated API; this is a business decision that is best communicated other ways.
For more information on using the @deprecated Javadoc tag, see Javadoc - The Java API Documentation Generator.

Example

The following examples show how to use the @deprecated Javadoc tag. They also illustrate the @Deprecated annotation, to emphasize that the two should be used together.
Here is an example of the most common form of a deprecated method (for Javadoc 1.2 and later):
/**
 * @deprecated  As of release 1.3, replaced by {@link #getPreferredSize()}
 */
@Deprecated public Dimension preferredSize() {
return getPreferredSize();
}
If the API reorganization was more than renaming, the deprecation may be more complex. Here is an example of a method that is being retracted:
/**
 * Delete multiple items from the list.
 *
 * @deprecated  Not for public use.
 *    This method is expected to be retained only as a package
 *    private method.  Replaced by
 *    {@link #remove(int)} and {@link #removeAll()}
 */
@Deprecated public synchronized void delItems(int start, int end) {
...
}

Difference between Java and J2EE


Core Java refers to the core or basic features of java like object orientation, inheritance, classes, objects, threads, etc. It is used to create simple java applications.


J2EE stands for Java 2 Enterprise Edition. It uses features like Servlets, JSPs, Struts, Hibernate etc which are all advanced J2EE concepts that are built on top of java.

Java is a object-oriented programming language which is platform neutral. That is unlike C or C++ java programs, Java can be run on any operating system with its JVM.

J2EE is just a specification for server side programs. That is to support internet applications, distributed and uses component model. So that Enterprises use this server side technology in their distributed business.

Since J2EE is just a server side specification, anybody can implement the specification but again using Java.
Hence today we have Custom implemented J2EE servers from Oracle, SUN, IBM and so on..

Your First Java Program: Hello World


In this section, our plan is to lead you into the world of Java programming by taking you through the three basic steps required to get a simple program running. The Java system is a collection of applications not unlike any of the other applications that you are accustomed to using (such as your word processor, e-mail program, or internet browser). As with any application, you need to be sure that Java is properly installed on your computer. You also need an editor and a terminal application. Here are system specific instructions for three popular home operating systems. [ Mac OS X · Windows · Linux ]

Programming in Java.

 We break the process of programming in Java into three steps:
  1. Create the program by typing it into a text editor and saving it to a file named, say, MyProgram.java.
  2. Compile it by typing "javac MyProgram.java" in the terminal window.
  3. Run (or execute) it by typing "java MyProgram" in the terminal window.
The first step creates the program; the second translates it into a language more suitable for machine execution (and puts the result in a file namedMyProgram.class); the third actually runs the program.
  • Creating a Java program. A program is nothing more than a sequence of characters, like a sentence, a paragraph, or a poem. To create one, we need only define that sequence characters using a text editor in the same way as we do for e-mail. HelloWorld.java is an example program. Type these character into your text editor and save it into a file named HelloWorld.java.
    public class HelloWorld { 
       public static void main(String[] args) { 
          System.out.println("Hello, World");
       }
    }
    
  • Compiling a Java program. At first, it might seem to you as though the Java programming language is designed to be best understood by the computer. Actually, to the contrary, the language is designed to be best understood by the programmer (that's you). A compiler is an application that translates programs from the Java language to a language more suitable for executing on the computer. It takes a text file with the .java extension as input (your program) and produces a file with a .class extension (the computer-language version). To compile HelloWorld.java type the boldfaced text below at the terminal. (We use the % symbol to denote the command prompt, but it may appear different depending on your system.)
    % javac HelloWorld.java
    
    If you typed in the program correctly, you should see no error messages. Otherwise, go back and make sure you typed in the program exactly as it appears above.
  • Executing a Java program. Once you compile your program, you can run it. This is the exciting part, where the computer follows your instructions. To run the HelloWorld program, type the following at the terminal:
    % java HelloWorld
    
    If all goes well, you should see the following response
    Hello, World
    
  • Understanding a Java program. The key line with System.out.println() send the text "Hello, World". When we begin to write more complicated programs, we will discuss the meaning of publicclassmainString[]argsSystem.out, and so on.
  • Creating your own Java program. For the time being, all of our programs will be just like HelloWorld.java, except with a different sequence of statements in main(). The easiest way to write such a program is to:
    • Copy HelloWorld.java into a new file whose name is the program name followed by .java.
    • Replace HelloWorld with the program name everywhere.
    • Replace the print statement by a sequence of statements.

Errors.

 Most errors are easily fixed by carefully examining the program as we create it, in just the same way as we fix spelling and grammatical errors when we type an e-mail message.
  • Compile-time errors. These errors are caught by the system when we compile the program, because they prevent the compiler from doing the translation (so it issues an error message that tries to explain why).
  • Run-time errors. These errors are caught by the system when we execute the program, because the program tries to peform an invalid operation (e.g., division by zero).
  • Logical errors. These errors are (hopefully) caught by the programmer when we execute the program and it produces the wrong answer. Bugs are the bane of a programmer's existence. They can be subtle and very hard to find.
One of the very first skills that you will learn is to identify errors; one of the next will be to be sufficiently careful when coding to avoid many of them.

Input and output.

 Typically, we want to provide input to our programs: data that they can process to produce a result. The simplest way to provide input data is illustrated in UseArgument.java. Whenever this program is executed, it reads the command-line argument that you type after the program name and prints it back out to the terminal as part of the message.
% javac UseArgument.java
% java UseArgument Alice
Hi, Alice. How are you?
% java UseArgument Bob
Hi, Bob. How are you?

Q + A

Q. Why Java?
A. The programs that we are writing are very similar to their counterparts in several other languages, so our choice of language is not crucial. We use Java because it is widely available, embraces a full set of modern abstractions, and has a variety of automatic checks for mistakes in programs, so it is suitable for learning to program. There is no perfect language, and you certainly will be programming in other languages in the future.
Q. Do I really have to type in the programs in the book to try them out?
A. Everyone should type in HelloWorld.java, but you can find all of the code in this book (and much more) on this booksite.
Q. What are Java's rules regarding tabs, spaces and newline characters?
A. There are not many. Java compilers treat them all to be equivalent. For example, we could also write HelloWorld as follows:
public class HelloWorld { public static void main ( 
String [] args) { System.out.println("Hello World") ; } }
But we do normally adhere to spacing and indenting conventions when we write Java programs, just as we always indent paragraphs and lines consistently when we write prose or poetry.
Q. What are the rules regarding quotation marks?
A. Material inside quotation marks is an exception to the rule of the previous question: things within quotes are taken literally so that you can precisely specify what gets printed. If you put any number of successive spaces within the quotes, you get that number of spaces in the output. If you accidentally omit a quotation mark, the compiler may get very confused, because it needs that mark to distinguish between characters in the string and other parts of the program. To print a quotation mark, a newline, or a tab, use \"\n, or \t, respectively, within the quotation marks.
Q. What is the meaning of the words publicstatic and void?
A. These keywords specify certain properties of main() that you will learn about later in the book. For the moment, we just include these keywords in the code (because they are required) but do not refer to them in the text.
Q. What happens when you omit a brace or misspell one of the words, like public or static or main? A. It depends upon precisely what you do. Such errors are called syntax errors. Try it out and see.
Q. Can a program use more than one command-line argument?
A. Yes, you can put several, though we normally use only a few. You refer to the second one as args[1], the third one as args[2], and so forth. Note that we start counting from 0 in Java.
Q. What Java systems libraries and methods are available for me to use?
A. There are thousands of them, but we introduce them to you in a deliberate fashion in this book to avoid overwhelming you with choices.
Q. How should I format my code? How should I comment my code?
A. Programmers use coding guidelines to make programs easier to read, understand, and maintain. As you gain experience, you will develop a coding style, just as you develop style when writing prose. Appendix B provides some guidelines for formatting and commenting your code. We recommend returning to this appendix after you've written a few programs.
Q. What exactly is a .class file?
A. It's a binary file (sequence of 0s and 1s). If you are using Unix or OS X, you can examine its contents by typing od -x HelloWorld.class at the command prompt. This displays the results in hexadecimal (base 16). In deference to Java's name, the first word of every .class file is cafe.

Exercises

  1. Write a program TenHelloWorlds.java that prints "Hello, World" ten times.
  2. Describe what happens if, in HelloWorld.java, you omit
    1. public
    2. static
    3. void
    4. args
  3. Describe what happens if, in HelloWorld.java, you misspell (by, say, omitting the second letter)
    1. public
    2. static
    3. void
    4. args
  4. Describe what happens if you try to execute Hi.java with:
    1. java Hi
    2. java Hi @!&^%
    3. java Hi 1234
    4. java Hi.class Bob
    5. java Hi.java Bob
    6. java Hi Alice Bob
  5. Modify UseArgument.java to make a program UseThree.java that takes three names and prints out a proper sentence with the names in the reverse of the order given, so that for example, "java UseThree Alice Bob Carol" gives "Hi Carol, Bob, and Alice.".

Monday, 17 September 2012

Transaction Processing


JDBC Transactions

JDBC transactions are controlled through the Connection object. There are two modes for managing transactions within JDBC:
  • auto-commit
  • manual-commit.
The setAutoCommit method is used to switch between the two modes.

Auto-commit Mode

Auto-commit mode is the default transaction mode for JDBC. When a connection is made, it is in auto-commit mode until setAutoCommit is used to disable auto-commit.
In auto-commit mode each individual statement is automatically committed when it completes successfully, no explicit transaction management is necessary. However, the return code must still be checked, as it is possible for the implicit transaction to fail.

Manual-commit Mode

When auto-commit is disabled, i.e. manual-commit is set, all executed statements are included in the same transaction until it is explicitly completed.
When an application turns auto-commit off, the next statement against the database starts a transaction. The transaction continues either the commit or the rollback method is called. The next command sent to the database after that starts a new transaction.
Calling the commit method ends the transaction. At that stage, Mimer SQL checks whether the transaction is valid and raises an exception if a conflict is identified.
If a conflict is encountered, the application determines how to continue, for example whether to automatically retry the transaction or inform the user of the failure. The application is notified about the conflict by an exception that must be caught and evaluated.
A request to rollback a transaction causes Mimer SQL to discard any changes made since the start of the transaction and to end the transaction.
Use the commit or rollback methods, rather than using the SQL COMMIT or ROLLBACK statements to complete transactions, for example:
 Statement stmt;
 int transactionAttempts;
 
 final int MAX_ATTEMPTS = 5; // Maximum transaction attempts
 
 // Open a connection
 url = "jdbc:mimer:/ExampleDB";
 con = DriverManager.getConnection(url, "MIMER_ADM", "admin");
 
 con.setAutoCommit(false); // Explicit transaction handling
 
 stmt = con.createStatement();
 
 // Loop until transaction successful (or max attempts exceeded)
 for (transactionAttempts = 1; ; transactionAttempts++) {
     // Perform an operation under transaction control
     stmt.executeUpdate("UPDATE mimer_store.currencies"
                      + "   SET exchange_rate = exchange_rate * 1.05"
                      + "   WHERE code = 'USD'");
 
     try {
         con.commit(); // Commit transaction
 
         System.out.println("Transaction successful");
         break;
 
     } catch(SQLException sqe) {
         // Check commit error - allow serialization failure
         if (sqe.getSQLState().equals("40001")) {
             // Check number of times the transaction has been attempted
             if (transactionAttempts >= MAX_ATTEMPTS) {
                 // Raise exception with application defined SQL state
                 throw new SQLException("Transaction failure", "UET01");
             }
         }
         else {
             // Raise all other exceptions to outer handler
             throw sqe;
         }
     } finally {
         con.close();
     }
 }

Setting the Transaction Isolation Level

The setTransactionIsolation method sets the transaction isolation level. The default isolation level for Mimer SQL is TRANSACTION_REPEATABLE_READ.
Note: With Enterprise Java Beans, the EJB environment provides the transaction management and therefore explicit transaction management is not required.

Executing an SQL Statement

The Connection object supports three types of Statement objects that can be used to execute an SQL statement or stored procedure:
  • a Statement object is used to send SQL statements to the database
  • the PreparedStatement interface inherits from Statement
  • the CallableStatement object inherits both Statement and PreparedStatement methods.

Using a Statement Object

The Connection method createStatement is used to create a Statement object that can be used to execute SQL statements without parameters.
The executeUpdate method of the Statement object is used to execute an SQL DELETE, INSERT, or UPDATE statement, i.e. a statement that does not return a result set, it returns an int indicating the number of rows affected by the statement, for example:
 int rowCount;
 
 stmt = con.createStatement();
 
 rowCount = stmt.executeUpdate(
                    "UPDATE mimer_store.currencies"
                  + "   SET exchange_rate = exchange_rate * 1.05"
                  + "   WHERE code = 'USD'");
 
 System.out.println(rowCount + " rows have been updated");

Using a PreparedStatement Object

Where an SQL statement is being repeatedly executed, a PreparedStatement object is more efficient than repeated use of the executeUpdate method against a Statement object.
In this case the values for the parameters in the SQL statement (indicated by ?) are supplied with the setXXX method, where XXX is the appropriate type for the parameter.
For example:
 PreparedStatement pstmt;
 int rowCount;
 
 pstmt = con.prepareStatement(
                    "UPDATE mimer_store.currencies"
                  + "   SET exchange_rate = exchange_rate * ?"
                  + "   WHERE code = ?");
 
 pstmt.setFloat(1, 1.05f);
 pstmt.setString(2, "USD");
 rowCount = pstmt.executeUpdate();
 
 pstmt.setFloat(1, 1.08f);
 pstmt.setString(2, "GBP");
 rowCount = pstmt.executeUpdate();

Using a CallableStatement Object

Similarly, when using stored procedures, a CallableStatement object allows parameter values to be supplied, for example:
 CallableStatement cstmt;
 
 cstmt = con.prepareCall("CALL mimer_store.order_item( ?, ?, ? )");
 
 cstmt.setInt(1, 700001);
 cstmt.setInt(2, 60158);
 cstmt.setInt(3, 2);
 cstmt.executeUpdate();
 
The setNull method allows a JDBC null value to be specified as an IN parameter. Alternatively, use a Java null value with a setXXX method.
For example:
 pstmt.setString(4, null);
 
A more complicated example illustrates how to handle an output parameter:
 CallableStatement cstmt;
 
 cstmt = con.prepareCall("CALL mimer_store.age_of_adult( ?, ? )");
 
 cstmt.setString(1, "US");
 cstmt.registerOutParameter(2, Types.CHAR);
 
 cstmt.executeUpdate();
 System.out.println(cstmt.getString(2) + " years");

Batch Update Operations

JDBC provides support for batch update operations. The BatchUpdateException class provides information about errors that occur during a batch update using the Statement method executeBatch.
The class inherits all the method from the class SQLException and also the method getUpdateCounts which returns an array of update counts for those commands in the batch that were executed successfully before the error was encountered.
For example:
 try {
 
 ...
 
 } catch(BatchUpdateException bue) {
     System.err.println("\n*** BatchUpdateException:\n");
 
     int [] affectedCount = bue.getUpdateCounts();
     for (int i = 0; i < affectedCount.length; i++) {
         System.err.print(affectedCount[i] + "  ");
     }
     System.err.println();
 
     System.err.println("Message:     " + bue.getMessage());
     System.err.println("SQLState:    " + bue.getSQLState());
     System.err.println("NativeError: " + bue.getErrorCode());
     System.err.println();
 
     SQLException sqe = bue.getNextException();
     while (sqe != null) {
         System.err.println("Message:     " + sqe.getMessage());
         System.err.println("SQLState:    " + sqe.getSQLState());
         System.err.println("NativeError: " + sqe.getErrorCode());
         System.err.println();
 
         sqe = sqe.getNextException();
     }
 }
 
Note: The BatchUpdateException object points to a chain of SQLException objects.

Enhancing Performance

The batch update functionality allows the statement objects to support the submission of a number of update commands as a single batch.
The ability to batch a number of commands together can have significant performance benefits. The methods addBatch, clearBatch and executeBatch are used in processing batch updates.
The PreparedStatement example above could be simply rewritten to batch the commands.
For example:
 PreparedStatement pstmt;
 int [] affectedCount;
 
 pstmt = con.prepareStatement(
                    "UPDATE mimer_store.currencies"
                  + "   SET exchange_rate = exchange_rate * ?"
                  + "   WHERE code = ?");
 
 pstmt.setFloat(1, 1.05f);
 pstmt.setString(2, "USD");
 pstmt.addBatch();
 
 pstmt.setFloat(1, 1.08f);
 pstmt.setString(2, "GBP");
 pstmt.addBatch();
 
 affectedCount = pstmt.executeBatch();
 
The Mimer SQL database server executes each command in the order it was added to the batch and returns an update count for each completed command.
If an error is encountered while a command in the batch is being processed then a BatchUpdateException is thrown (see Error Handling) and the unprocessed commands in the batch are ignored.
In general it may be advisable to treat all the commands in the batch as a single transaction, allowing the application to have control over whether those commands that succeeded are committed or not.
Set the Connection object's auto-commit mode to off to group the statements together in a single transaction. The application can then commit or rollback the transaction as required.
Calling the method clearBatch clears a Statement object's list of commands.
Using the Close method to close any of the Statement objects releases the database and JDBC resources immediately. It is recommended that Statement objects be explicitly closed as soon as they are no longer required.

Result Set Processing

There are a number of ways of returning a result set. Perhaps the simplest is as the result of executing an SQL statement using the executeQuery method, for example:
 Statement stmt;
 ResultSet rs;
 
 stmt = con.createStatement();
 
 rs = stmt.executeQuery("SELECT *"
                      + "   FROM mimer_store.currencies");
 
 while (rs.next()) {
     System.out.println(rs.getString("CURRENCY"));
 
A ResultSet can be thought of as an array of rows. The 'current row' is the row being examined and manipulated at any given time, and the location in the ResultSet is the 'current row position'.
Information about the columns in a result set can be retrieved from the metadata, for example:
 Statement stmt;
 ResultSet rs;
 ResultSetMetaData rsmd;
 
 stmt = con.createStatement();
 
 rs = stmt.executeQuery("SELECT *"
                      + "   FROM mimer_store.currencies");
 
 rsmd = rs.getMetaData();
 for (int i = 1; i <= rsmd.getColumnCount(); i++) {
     System.out.println(rsmd.getColumnName(i));
     System.out.println(" Type: " + rsmd.getColumnTypeName(i));
     System.out.println(" Size: " + rsmd.getColumnDisplaySize(i));
 }

Scrolling in Result Sets

The previous examples used forward-only cursors (TYPE_FORWARD_ONLY), which means that they only support fetching rows serially from the start to the end of the cursor, this is the default cursor type.
In modern, screen-based applications, the user expects to be able to scroll backwards and forwards through the data. While it is possible to cache small result sets in memory on the client, this is not feasible when dealing with large result sets. Support for scrollable cursors provide the answer.
Scrollable cursors allow you to move forward and back as well as to a particular row within the ResultSet. With scrollable cursors it is possible to iterate through the result set many times.
The Mimer drivers' scrollable cursors are of type TYPE_SCROLL_INSENSITIVE, which means that the result set is scrollable but also that the result set does not show changes that have been made to the underlying database by other users, i.e. the view of the database is consistent. To allow changes to be reflected may cause logically inconsistent results.

Positioning the Cursor

There are a number of methods provided to position the cursor:
  • absolute
  • afterLast
  • beforeFirst
  • first
  • last
  • next
  • previous
  • relative
There are also methods to determine the current position of the cursor:
  • isAfterLast
  • isBeforeFirst
  • isFirst
  • isLast
The getRow method returns the current cursor position, starting from 1. This provides a simple means of finding the number of rows in a result set.
For example:
 Statement stmt;
 ResultSet rs;
 
 stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_READ_ONLY);
 
 rs = stmt.executeQuery("SELECT code, currency"
                      + "   FROM mimer_store.currencies"
                      + "   WHERE code LIKE 'A%'");
 
 System.out.println("\nOriginal sort order");
 while (rs.next()) {
     System.out.println(rs.getString(1) + "  " + rs.getString(2));
 }
 
 System.out.println("\nReverse order");
 while (rs.previous()) {
     System.out.println(rs.getString(1) + "  " + rs.getString(2));
 }
 
 rs.last();
 System.out.println("\nThere are " + rs.getRow() + " rows");
 
The Mimer JDBC Driver will automatically perform a pre-fetch whenever a result set is created. This means that a number of rows are transferred to the client in a single communication across the network. If only a small number of rows are actually required use setMaxRows to limit the number of rows returned in the result set.

Result Set Capabilities

A instance of the ResultSet class is created when a query is executed. The capabilities of the result set depend on the arguments used with the createStatement (or prepareStatement or prepareCall) method.
The first argument defines the type of the ResultSet, whether it is scrollable or non-scrollable, and the second argument defines the concurrency option, i.e. the update capabilities.
A ResultSet should only be made updatable if the functionality is going to be used, otherwise the option CONCUR_READ_ONLY should be used. If used, both the type and the concurrency option must be specified.
The following example creates a scrollable result set cursor that is also updatable:
 stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_UPDATABLE);
 
Even if the options used specify that the result set will be scrollable and updatable, it is possible that the actual SQL query will return a ResultSet that is non-scrollable or non-updatable.

Holdable cursors

The mimjdbc3.jar driver supports the JDBC 3 specification. As such it provides an opportunity for application developers to create holdable cursors. The difference between a holdable cursor and a regular cursor is that regular cursors are closed at the end of the transaction. The holdable cursor can (theoretically) stay opened for an unlimited period of time. However, leaving a cursor open for a long period of time may have serious performance implications for the same reason long lasting transactions may impair server performance.

Updating Data

Applications can update data by executing the UPDATE, DELETE, and INSERT statements. An alternative method is to position the cursor on a particular row and then use DELETE CURRENT, or UPDATE CURRENT statements.
The following example illustrates how this can be done:
 Statement select;
 PreparedStatement update;
 ResultSet rs;
 
 select = con.createStatement(ResultSet.TYPE_FORWARD_ONLY,
                              ResultSet.CONCUR_UPDATABLE);
 
 select.setCursorName("CRN"); /* Name the cursor */
 
 rs = select.executeQuery("SELECT currency"
                        + "   FROM mimer_store.currencies"
                        + "   WHERE code = 'ALL'"
                        + "   FOR UPDATE OF currency");
 
 update = con.prepareStatement("UPDATE mimer_store.currencies"
                             + "   SET currency = ?"
                             + "   WHERE CURRENT OF crn");
 
 while (rs.next()) {
     if (rs.getString("CURRENCY").startsWith("Leke")) {
         update.setString(1, "Albanian Leke");
     }
     else {
          update.setString(1, "Leke");
     }
     update.executeUpdate();
 }

User-Defined Types

Whenever the application working with user-defined types, a type mapping is used. For DISTINCT types, the default type mapping is given by the core SQL type which makes up the DISTINCT type. A structured type is mapped by default to a predefined JDBC interface which provides a basic functionality to work with its attributes.
Applications may alter the type mapping to integrate its own type classes with the database types. The custom type mapping will allow JDBC getter and setter methods to work directly with the classes in the application.

Default Type Mapping

By default, when fetching a user defined type from the database or supplying one to the database, the generic class java.sql.Struct is being used to hold the type attributes. Objects of this class simply holds an array of objects, each one corresponding the attribute in question.
For example, consider the following SQL type:
 create type NAME as (TITLE nvarchar(20),
                      GIVEN_NAME nvarchar(50),
                      FAMILY_NAME nvarchar(50));
 
When retrieving columns of this type, the method ResultSet.getObject is used, which returns a java.sql.Struct object. For example:
ResultSet rs = stmt.executeQuery("select EMPLOYEE_NAME from EMPLOYEES"); while (rs.next()) { Struct employee_name = rs.getObject(1); Object[] employee_name_attributes = employee_name.getAttributes(); String title = (String)employee_name_attributes[0]; String given_name = (String)employee_name_attributes[1]; String family_name = (String)employee_name_attributes[2]; /* At this point the respective attributes are available in the above String objects for further processing. */ } rs.close();

Custom Java Classes With Type Mapping

A more involved way is to map the SQL type against a Java class which implements the java.sql.SQLData interface. When mapping the SQL type name, the Java class might look like this:
 import java.sql.*;
 
 public class Name implements SQLData {
    String title,given_name,family_name;
    String type_name;
 
    /* SQLData interface routines. */
 
    public String getSQLTypeName() {
        return type_name;
    }
 
    public void readSQL(java.sql.SQLInput stream,String typeName) throws 
java.sql.SQLException
    {
        type_name = typeName;
        title = stream.readString();
        given_name = stream.readString();
        family_name = stream.readString();
    }
 
    public void writeSQL(java.sql.SQLOutput stream) throws 
java.sql.SQLException
    {
        stream.writeString(title);
        stream.writeString(given_name);
        stream.writeString(family_name);
    }
 
    /* Here follows additional methods to define the characteristics of
       this class.
     * This might be ordinary setter/getter methods for applications to use,
       for example the following
     */
 
    public String getCombinedName()
    {
        if (title!=null && title.length()>0)
            return title+" "+given_name+" "+family_name;
        return given_name+" "+family_name;
    }
 
    public String getTitle()
    {
        return title;
    }
 
    public void setTitle(String title)
    {
        this.title = title;
    }
 
    public String toString()
    {
        return getCombinedName();
    }
 }
 
The application must register its own type mapping with the connection to make the JDBC driver aware of the custom class. Whenever the custom type map is activated, the JDBC methods getObject and setObject will return and accept parameters of the specified class, for example the following will create a map between the SQL type MYSCHEMA.NAME and the Java class Name.
 java.util.Map map = con.getTypeMap();
 map.put("MYSCHEMA.NAME", Class.forName("Name"));
 con.setTypeMap(map);

Programming Considerations

Below is a summary of issues to be considered when programming with Mimer JDBC.

Interval Data

Both the JDBC specification and the Java language lack support for INTERVAL data types.
You can use the getString and setString methods for values accessed by a driver from database columns containing INTERVAL data.

Closing Objects

Although Java has automatic garbage collection, it is essential that you close JDBC objects, such as ResultSets, Statements and Connections, when done with them.
Closing objects gives your application better control over resources.
If you don't close objects, resources are kept allocated in the database server until garbage collection is triggered, this can exhaust server resources.

Increasing Performance

  • Use Stored Procedures
    One of the main issues when trying to increase performance is to reduce network traffic. For example, you can increase performance by using the database server to return more accurate data instead of returning a large amount of unqualified data which your application must handle. You can achieve this by using more sophisticated SQL statements or by using stored procedures (PSM).
  • Use More Than One Connection
    Mimer JDBC drivers are thread-safe and use one lock per connection. So, to achieve higher concurrency, an application should use several connections.
  • Prefetching Data
    The drivers are implemented to perform automatic prefetch, i.e. whenever a resultSet is created, a buffer is filled with successive rows. This is an optimization for throughput, allowing more data to be fetched to the client in the single communication made.
    The flip side of the coin is that response time, i.e. the time it takes to receive the first record, may be increased (see Use setMaxRows below.)
  • Use setMaxRows
    If you know that only a small number of records are to be fetched, then you can use the setMaxRows method to optimize the response time, i.e. to avoid an array fetch.
  • Use PreparedStatements
    Another way of increasing performance is to avoid recompiling SQL statements unnecessarily. Whenever you use Statement.executeXXX methods, statements are compiled. Instead, use parameterized precompiled statements, i.e. PreparedStatement, whenever possible.
  • Use Batched Statements
    Using the Mimer JDBC Driver version 2 or later, you can reduce the number of network requests by using batched statements.
    If, for example, you replace 20 calls to Statement.execute() with 20 calls to Statement.addBatch() followed by a Statement.executeBatch() call, 20 server network requests are replaced by a single network request.
    If response time is an issue, this simple change may give a twenty-fold performance improvement!
    Note that batched statements for PreparedStatement and CallableStatement differ from the implementation for the Statement class. When using PreparedStatement or CallableStatement, only a single SQL statement can be used in a batch. The addBatch() call (without argument) adds a set of parameters to the batch. When you use batches, the same SQL statement is called repeatedly with different parameters in a single network request.
    In versions 2 and later, you can use the setFetchSize method to control the amount of data fetched.
Related Posts Plugin for WordPress, Blogger...