ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Stored Procedures for Java Programmers

by Nic Ferrier
08/13/2003

This article explains how to use DBMS stored procedures. I explain the basics and some advanced features such as returning ResultSets. The article presumes you are fairly familiar with DBMSs and with JDBC. It also assumes you're fairly comfortable reading code in a foreign language (that is, not Java), but does not expect any previous stored procedure experience.

A stored procedure is a program that is kept and executed within a database server. You call the procedure from a Java class using a special syntax. When you call it, the name of the procedure and the parameters you specify are sent over the JDBC connection to the DBMS, which executes the procedure and returns the results (if any) back over the connection.

Using stored procedures has a lot of the same advantages as using application servers based on EJBs or CORBA. The difference is that stored procedures come free with lots of popular DBMSs, while application servers are mostly expensive. This isn't just an issue of license cost. The time it takes to administer and write code for app servers, and the increased complexity of the client applications that rely on them, can be almost wholly replaced by a reliance on your DBMS.

You can write your stored procedures in Java, Python, Perl, or C, but they are most often written in a language specific to the DBMS you're using. Oracle uses PL/SQL, PostgreSQL uses pl/pgsql, and DB2 uses Procedural SQL. These languages are all very similar. Porting between them is no more difficult than porting Session Beans between versions of Sun's EJB spec. In addition, stored procedure languages are designed for embedding SQL, which makes them much better for expressing the database mechanics than languages like Java or C.

Because stored procedures run in the DBMS itself, they can help to reduce latency in applications. Rather than executing four or five SQL statements in your Java code, you just execute one stored procedure that does the operations for you on the server side. Reducing the number of network trips alone can have a dramatic effect on performance.

Using Stored Procedures

Plain old JDBC supports calling stored procedures with the CallableStatement class. That class is actually a subclass of PreparedStatement. Imagine that we have a database of poets. The database has a stored procedure to set a poet's age at death. Here's an example of calling that stored procedure with details about the old soak Dylan Thomas:

try
{
    int age = 39;
    String poetName = "dylan thomas";
    CallableStatement proc =
        connection.prepareCall("{ call set_death_age(?, ?) }");
    proc.setString(1, poetName);
    proc.setInt(2, age);
    cs.execute();
}
catch (SQLException e)
{
    // ....
}

Related Reading

JDBC Pocket Reference
By Donald Bales

The string passed to the prepareCall method is the procedure call specification. It specifies the name of the procedure to call and a ? for each parameter you need to specify.

Integration with JDBC is a big advantage for stored procedures: in order to call a procedure from your application, you need no stub classes or config files, and nothing except the JDBC driver for your DBMS.

When this code is executed, the database procedure is called. We don't get a result because the procedure doesn't return one. Success or failure can be signalled with exceptions. Failure can mean a failure when calling the procedure (such as one of the arguments being specified with the wrong type), or an application failure (such as throwing an exception to indicate that "Dylan Thomas" doesn't exist in the database of poets).

Combining SQL Operations with Procedures

Mapping Java objects to rows in SQL tables is simple enough, but it usually involves executing several SQL statements; maybe a SELECT to find a row ID followed by an INSERT of the data with the specified row ID. In a highly normalized schema, there might be multiple tables to update, and therefore many more statements. The Java code can quickly get bloated and the network overhead for each statement soon adds up.

Moving all of those SQL statements into a stored procedure makes life much simpler and involves only one network call. All of the associated SQL operations can take place inside of the database. In addition, stored procedure languages such as PL/SQL allow you to speak SQL much more naturally than is possible in Java. Here's our earlier stored procedure written using Oracle's PL/SQL language:

create procedure set_death_age(poet VARCHAR2, poet_age NUMBER)
    poet_id NUMBER;
begin
  SELECT id INTO poet_id FROM poets WHERE name = poet;
  INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age);
end set_death_age;

Unusual implementation, no? I bet you expected to see an UPDATE on the poets table? This is an indication of how easy it is to implement things when you use stored procedures. set_death_age is almost certainly badly implemented. We should probably just have a column on the poets table. It doesn't matter to the Java code what the database schema implementation is, because our Java code just calls the procedure. We can change the schema and the procedure later to improve performance, but we won't have to change our Java code.

Here's a Java method to call the above procedure:

public static void setDeathAge(Poet dyingBard, int age)
    throws SQLException
{
   Connection con = null;
   CallableStatement proc = null;

   try
   {
      con  = connectionPool.getConnection();
      proc = con.prepareCall("{ call set_death_age(?, ?) }");
      proc.setString(1, dyingBard.getName());
      proc.setInt(2, age);
      proc.execute();
   }
   finally
   {
      try
      {
         proc.close();
      }
      catch (SQLException e) {}
      con.close();
   }
}

Using static methods like this is a good way to ensure maintainability. It also makes the code that calls stored procedures into simple boilerplate code. If you're using a lot of stored procedures, you'll find yourself just using cut and paste to create methods. Because of the formulaic nature of the code, it's also possible to script the production of code to call stored procedures.

Pages: 1, 2

Next Pagearrow