FileDocCategorySizeDatePackage
DatabasePeer.javaAPI DocExample7351Fri Jul 18 21:05:32 BST 1997imaginary.persist

DatabasePeer.java

/**
 * The DatabasePeer class implements the persistence methods from
 * PersistentPeer and performs the actual database access for
 * individual persistent objects.  Of course, at this level it is impossible
 * to know everything about the application in order to isolate database
 * access completely.  Applications requiring database persistence
 * should extend this class and implement the abstract methods that
 * allow an application to formulate the SQL.
 */
package imaginary.persist;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;

public abstract class DatabasePeer implements PersistentPeer {
    /**
     * Subclasses must implement this method to build an INSERT
     * statement for the specified persistent object.
     * @param p the Persistent that is being inserted into the database
     * @return the SQL string to be sent to the database
     */
    protected abstract String getInsertSql(Persistent p);

    /**
     * Subclasses must implement this method to build a DELETE
     * statement for the specified persistent object.
     * @param p the Persistent that is being deleted from the database
     * @return the SQL DELETE statement
     */
    protected abstract String getRemoveSql(Persistent p);

    /**
     * Subclasses must implement this method to build a SELECT
     * statement that will restore only the named persistent object.
     * At the time it gets passed to this method, the persistent
     * object has only its ID set.  All other values are awaiting
     * a restore operation.
     * @param p the Persistent that is being restored from the database
     * @return the SQL SELECT statement
     */
    protected abstract String getRestoreSql(Persistent p);

    /**
     * Subclasses must implement this method to build an UPDATE
     * statement that will update the specified persistent object.
     * @param p the Persistent object to be updated
     * @return the SQL UPDATE statement
     */
    protected abstract String getUpdateSql(Persistent p);

    /**
     * This method implements the insert persistence operation
     * as prescribed by the PersistentPeer interface.  It asks
     * its subclasses for the proper SQL and then triggers
     * a save using that SQL statement.
     * @param p the persistent object to be inserted
     * @param t the DatabaseTransaction to use for that insert
     * @exception imaginary.persist.PersistenceException An error occurred
     * in saving the object to the database.
     */
    public void insert(Persistent p, Transaction t)
    throws PersistenceException {
        save((DatabaseTransaction)t, getInsertSql(p));
    }

    /**
     * This method implements the remove persistence operation
     * as prescribed by the PersistentPeer interface.  It asks
     * its subclasses for the proper SQL and then triggers
     * a save using that SQL statement.
     * @param p the persistent object to be removed
     * @param t the DatabaseTransaction to use for that removal
     * @exception imaginary.persist.PersistenceException An error occurred
     * in removing the object from the database.
     */
    public void remove(Persistent p, Transaction t)
    throws PersistenceException {
        save((DatabaseTransaction)t, getRemoveSql(p));
    }

    /**
     * This method implements the restore persistence operation
     * as prescribed by the PersistentPeer interface.  It asks
     * its subclasses for the proper SQL and then triggers
     * a save using that SQL statement.
     * @param p the persistent object to be restored
     * @param trans the DatabaseTransaction to use for restoring the object
     * @exception imaginary.persist.PersistenceException An error occurred
     * in restoring the object from the database.
     */
    public void restore(Persistent p, Transaction trans)
    throws PersistenceException {
         String sql = getRestoreSql(p); // get the restore SQL
         Connection connection = null;
         Statement statement = null;
         ResultSet results = null;
         ResultSetMetaData meta = null;
        
         try {
             Hashtable h = new Hashtable(); // store the values here

             // Get the connection from the DatabaseTransaction
             connection = ((DatabaseTransaction)trans).getConnection();
             // Create a JDBC statement from the connection
             statement = connection.createStatement();
             // Execute the SQL
             results = statement.executeQuery(sql);
             // Get the meta data
             meta = results.getMetaData();
             // Make sure we got a row!
             if( !results.next() ) {
                 throw new PersistenceException("No rows found!");
             }
             // For each column in the result set
             for(int i=1; i<=meta.getColumnCount(); i++) {
                 Object ob = results.getObject(i);
                 // Put the value in the Hashtable using the column name
                 // as a key
                 h.put(meta.getColumnLabel(i), ob);
             }
             // Call the restore from Hashtable method in the Persistent
             p.restore(trans, h);
         }
         catch( SQLException e ) {
             if( statement != null ) { // This is not required
                 try { statement.close(); }
                 catch( SQLException e2 ) { }
             }
             throw new PersistenceException(e);
         }
    }

    //        * private methods generate no javadoc *
    // Because JDBC allows all statements that modify the database
    // go through the executeUpdate() method in java.sql.Statement,
    // we can encapsulate all of the persistence operations inside
    // a single method after we get the specific SQL.  This private
    // method takes any random SQL designed to modify the database
    // and executes it.
    private void save(DatabaseTransaction trans, String sql)
    throws PersistenceException {
        Connection connection = null;
        Statement statement = null;

        try {
            connection = trans.getConnection(); // Get the JDBC connection
            statement = connection.createStatement(); // Create a statement
            statement.executeUpdate(sql); // Execute the SQL
            statement.close(); // Close the statement (not required)
        }
        catch( SQLException e ) {
            if( statement != null ) { // not required
                try { statement.close(); }
                catch( SQLException e2) { }
            }
            throw new PersistenceException(e);
        }
    }

    /**
     * This method implements the update persistence operation
     * as prescribed by the PersistentPeer interface.  It asks
     * its subclasses for the proper SQL and then triggers
     * a save using that SQL statement.
     * @param p the persistent object to be updated
     * @param t the DatabaseTransaction to use for updating the object
     * @exception imaginary.persist.PersistenceException An error occurred
     * in updating the object in the database.
     */
    public void update(Persistent p, Transaction t)
    throws PersistenceException {
        save((DatabaseTransaction)t, getUpdateSql(p));
    }
}