📄 genericfactorybase.java
字号:
package org.ephman.abra.database;import java.sql.*;import java.util.*;import org.ephman.utils.*;import org.ephman.abra.utils.*;/** * FactoryBase class - base for all the JDBC based db factories. * * @author TPR * @version 0.1 */public abstract class GenericFactoryBase { // Create a default cache for objects. TODO: should be created in // a smarter way. // protected WeakCache objectCache = new WeakCache (); // TODO: WARNING if classes keep persistent copies of objects // they will no longer have the right copy after a cache flush public void flushCache () { // objectCache.flush (); } protected Connection getConnection (DatabaseSession dbSess) { return ((JDBCDatabaseSession)dbSess).getJdbcConnection(); } protected Identified getObject (DatabaseSession dbSess, String columnName, String value) throws SQLException { Identified result = null; String sql = getSelectSql(columnName); QueryResult qr = getResults (dbSess, sql, new PreparedFilter ("", value), null); ResultSet rs = qr.rs; if (rs.next ()) { result = makeObject (dbSess, rs); } qr.close (); return result; } protected Identified getObject (DatabaseSession dbSess, String columnName, int value) throws SQLException { Identified result = null; if (columnName.equals(getPrimaryColumn())) { result = dbSess.getItem (this, value); if (result != null) checkRefresh (dbSess, result); } if (result == null) { String sql = getSelectSql(columnName); QueryResult qr = getResults (dbSess, sql, value); ResultSet rs = qr.rs; if (rs.next ()) { result = makeObject (dbSess, rs); } qr.close (); } return result; } /** routine to store an object -- if new putNew is called * else update is called */ protected void storeObject (DatabaseSession dbSess, Identified item) throws SQLException { storeObject (dbSess, item, DEEP); // default to deep store } /** routine to store an object -- if new putNew is called * else update is called */ protected void storeObject (DatabaseSession dbSess, Identified item, int storageDepth) throws SQLException { if (item.getOid () == 0) // is a new item putNewObject (dbSess, item, storageDepth); else updateObject (dbSess, item, storageDepth); } /** routine to place a new object in the db * */ protected void putNewObject (DatabaseSession dbSess, Identified item) throws SQLException { putNewObject (dbSess, item, DEEP); //default to deep-storage } /** putNewObject stores an object for the first time using insert stmts */ protected void putNewObject (DatabaseSession dbSess, Identified item, int storageDepth) throws SQLException { if (storageDepth == DEEP) preStorage (dbSess, item); marshalObjects (item); PreparedStatement stmt = makeInsertStmt (dbSess); // System.out.println (stmt + "foo"); setArguments (stmt, item, false); QueryTracer.trace (this, "putnew"); ((JDBCDatabaseSession)dbSess).setCurrentStatement(stmt); boolean isOk = stmt.execute(); ((JDBCDatabaseSession)dbSess).setCurrentStatement(null); int count = stmt.getUpdateCount (); // stmt.close (); if (count != 1) { stmt.close (); throw new AbraSQLException ("ephman.abra.database.badinsert", new Integer(count)); } if (dbNeedsId ()) // most dbs will need to check a rtn val from function or call db to get currval item.setOid(getLastId (dbSess, stmt)); stmt.close (); // now close stmt dbSess.putItem (this, item); if (storageDepth == DEEP) deepStorage (dbSess, item); if (hasClobs ()) { updateClobs (dbSess, item); } // QueryTracer.trace (this, "finished w/ put new"); } public abstract boolean dbNeedsId (); /** generic. can override in descendant class if procs are supported */ protected PreparedStatement makeInsertStmt (DatabaseSession dbSess) throws SQLException { Connection conn = ((JDBCDatabaseSession)dbSess).getJdbcConnection (); if (useStoredProcs ()) return conn.prepareCall (makeInsertCall ()); else // just dynamic sql return conn.prepareStatement (makeInsertString()); } /* checks for procs if so makes.. */ protected PreparedStatement makeUpdateStmt (DatabaseSession dbSess) throws SQLException { Connection conn = ((JDBCDatabaseSession)dbSess).getJdbcConnection (); if (useStoredProcs ()) return conn.prepareCall (makeUpdateCall ()); else // just dynamic sql return conn.prepareStatement (makeUpdateString()); } protected void deleteObject (DatabaseSession dbSess, Identified item) throws SQLException { Connection conn = ((JDBCDatabaseSession)dbSess).getJdbcConnection (); String sql = "delete from " + getTableName () + " where " + getPrimaryColumn() + "=?"; //String sql = " update " + getTablename() + " set ( end_date = " + System.currentTimeMillis() + " ) where " + getPrimaryColumn() + "=?"; PreparedStatement stmt = conn.prepareStatement (sql); stmt.setInt(1, item.getOid()); QueryTracer.trace(this, sql, item.getOid ()); ((JDBCDatabaseSession)dbSess).setCurrentStatement(stmt); int count = stmt.executeUpdate(); ((JDBCDatabaseSession)dbSess).setCurrentStatement(null); stmt.close (); if (count != 1) throw new AbraSQLException ("ephman.abra.database.baddelete", new Integer(count)); //objectCache.get(OID); // objectCache.remove (item); // QueryTracer.trace(this, "finished w/ delete"); } /** deleteObjects will delete all the rows which match the given filter * @param dbSess the database connection * @param filter the query filter to apply * @return the number of rows affected */ protected int deleteObjects (DatabaseSession dbSess, QueryFilter filter) throws SQLException { Connection conn = ((JDBCDatabaseSession)dbSess).getJdbcConnection (); if (filter == null) throw new AbraSQLException ("ephman.abra.database.nodelfilter"); String sql = getDeleteSql (filter); //String sql = " update " + getTablename() + " set ( end_date = " + System.currentTimeMillis() + " ) where " + getPrimaryColumn() + "=?"; PreparedStatement stmt = conn.prepareStatement (sql); QueryTracer.trace(this, sql); ((JDBCDatabaseSession)dbSess).setCurrentStatement(stmt); int count = stmt.executeUpdate(); ((JDBCDatabaseSession)dbSess).setCurrentStatement(null); stmt.close (); return count; } protected void updateObject (DatabaseSession dbSess, Identified item) throws SQLException { updateObject (dbSess, item, DEEP); } protected int SHALLOW = 42; protected int DEEP = 34; // constants for deep and shallow retrieval protected void updateObject (DatabaseSession dbSess, Identified item, int storageDepth) throws SQLException { if (storageDepth == DEEP) { preStorage (dbSess, item); } marshalObjects (item); PreparedStatement stmt = makeUpdateStmt (dbSess); if (item instanceof Versioned) { Versioned v = (Versioned)item; v.setVersion (v.getVersion () + 1); // ((JDBCDatabaseSession)dbSess).addTransactionItem (v); } setArguments (stmt, item, true); QueryTracer.trace (this, "updateObject"); ((JDBCDatabaseSession)dbSess).setCurrentStatement(stmt); int count = stmt.executeUpdate (); ((JDBCDatabaseSession)dbSess).setCurrentStatement(null); stmt.close (); if (!useStoredProcs () && count != 1) throw new AbraSQLException ("ephman.abra.database.badupdate", new Integer(count)); if (storageDepth == DEEP) deepStorage (dbSess, item); if (hasClobs ()) { updateClobs (dbSess, item); } // QueryTracer.trace(this, "finished w/ update"); } public Vector queryObjects (DatabaseSession dbSess, String column, int key) throws SQLException { Vector result = null; Connection conn = ((JDBCDatabaseSession)dbSess).getJdbcConnection(); /*String sql = "select * from " + getTableName () + " where " + column + " =?"; */ String sql = this.getSelectSql(column); QueryResult qr = getResults (dbSess, sql, key); ResultSet rs = qr.rs; result = getCollection (dbSess, rs); qr.close (); return result; } /** a routine to get objects with a given DatabaseLookup.. * @param dbSess is the in-transaction database session * @param lookup a ViewLookup from the generated descendant of this class * @param filter an option filter to restrict hits */ public Vector queryObjects (DatabaseSession dbSess, ViewLookup lookup, QueryFilter filter) throws SQLException { return queryObjects (dbSess, lookup, filter, null); } public Vector queryObjects (DatabaseSession dbSess, ViewLookup lookup, QueryFilter filter, SortCriteria sortCriteria) throws SQLException { if (lookup.getFactory () != this) throw new AbraSQLException ("ephman.abra.database.wronglookfact"); String sqlString = lookup.getSqlString (); if (filter != null) { if (!sqlString.endsWith ("where ")) sqlString += " and "; } else if (sqlString.endsWith ("where ")) { //hack sqlString = sqlString.substring (0, sqlString.length () - 6); // remove 'where ' from string } QueryResult qr = getResults (dbSess, sqlString, filter, sortCriteria, false, "this"); ResultSet rs = qr.rs; Vector result = new Vector (); java.lang.reflect.Method rip = lookup.getExtractMethod (); Object [] params = new Object [] {rs}; while (rs.next ()) { Object item = null; try { item = rip.invoke (this, params); } catch (Exception e) { // e.printStackTrace(); e.printStackTrace(); qr.close (); if (e instanceof SQLException) throw (SQLException)e; else throw new AbraSQLException ("ephman.abra.database.badreflect", new Object[] { rip.getName (), e.getMessage ()}); } result.addElement(item); } qr.close (); return result; } /** A routine to lock an object and all of its sub parts in the database (thread locking) * which is only released when this thread commits/rollsback * * @param dbSess the current merlin session * @param item the Identified item to be locked (and even refreshed) * @throws SQLException when db-error occurs */ public void lock (DatabaseSession dbSess, Identified item) throws SQLException { if (item.getOid () == 0) { throw new AbraSQLException ("ephman.abra.database.badlock"); } String sql = makeLockSql(); ((JDBCDatabaseSession)dbSess).setLockingMode (); QueryResult qr = getResults (dbSess, sql, item.getOid()); ResultSet rs = qr.rs; if (item instanceof Versioned) { Versioned v = (Versioned)item; rs.next (); checkRefresh (dbSess, v, rs); // see if object (an sub pieces) need refreshing.. } ((JDBCDatabaseSession)dbSess).endLockingMode (); qr.close (); } // separate routine that can be overriden for specific database protected String makeLockSql () { return ("select * from " + getTableName () + " where (" + getPrimaryColumn() + "=?) for update"); } // returns whether procs are used for this class.. protected abstract boolean useStoredProcs (); protected abstract Identified makeFromResultSet (ResultSet rs) throws SQLException; protected abstract void refreshFromResultSet (Identified item, ResultSet rs) throws SQLException; protected abstract String makeUpdateString (); protected abstract String makeInsertString (); /** call to a stored proc for this object.. */ protected abstract String makeInsertCall (); /** call to a stored proc for this object.. */ protected abstract String makeUpdateCall (); protected abstract String getPrimaryColumn (); protected abstract String getTableName (); protected abstract void setArguments (PreparedStatement stmt, Object item, boolean update) throws SQLException; protected void deepRetrieval (DatabaseSession dbSess, Identified item) throws SQLException { // do nothing - override if your class needs to do specific deep lookups } protected void deepStorage (DatabaseSession dbSess, Identified item) throws SQLException { // do nothing - override if your class needs to do specific deep lookups } protected void marshalObjects (Identified item) throws SQLException { // do nothing - override if your class needs to marshal objects to xml // text before storing } protected void preStorage (DatabaseSession dbSess, Identified item) throws SQLException { // override if your object needs save db objects // before storing this object } public Vector getCollection (DatabaseSession dbSess, ResultSet rs) throws SQLException { Connection conn = getConnection (dbSess); Vector result = new Vector (); while (rs.next()) { //int oid = rs.getInt(getPrimaryColumn ()); Identified item = makeObject (dbSess, rs); result.add (item); } return result; } // regular queries.. (no cursors.. ) /** A routine to get a hits given the filter * @param dbSess the current merlin session * @param query the filter to delimit hits.. * * @throws SQLException if a db error occurs * @return Vector of results */ public Vector queryObjects (DatabaseSession dbSess, QueryFilter query) throws SQLException { return querySorted (dbSess, query, null); } /** A routine to get a all from the table * @param dbSess the current merlin session * * @throws SQLException if a db error occurs * @return Vector of results */ protected Vector queryAll (DatabaseSession dbSess) throws SQLException { return querySorted (dbSess, null, null); } /** A routine to get a all from the table - sorted * @param dbSess the current merlin session * @param sortBy the sorting criteria * * @throws SQLException if a db error occurs * @return Vector of results
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -