/**
* 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));
}
}
|