Alright,
        Have modified the Store Command to default to the priamary key
if the row id is null. I am surprised that am not getting the ROWID as
null anywhere except for in the ejbPostCreate method. If everyone is
happy with the way its been done in JDBCStoreEntityCommand, then please
give me a shout and I can do the same for the JDBCRemoveEntityCommand as
well. Alternatively, if there is something glaringly wrong then let me
know so that I can fix it.

Regards

Vinay

Here is the code.



1. Adding a field in jaws.xml called stable-rowid-column name. This is
ROWID for Oracle and can be something else for other databases. If you
do not
want to use this feature just don't specify the tag and it will use the
default mechansm based on the primary key.

2. Updated JawsEntityMetaData with

    //Enable fast updates based on stable row id column
    private String stableRowIdColumn;

    public String getStableRowIdColumn() { return stableRowIdColumn; }

      //Get row id for fast stable row id based updates/deletes and
inserts
        stableRowIdColumn = getElementContent(getOptionalChild(element,
"stable-rowid-column"));

3. Modified JDBCStoreEntityCommand  as follows,

/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.ejb.plugins.jaws.jdbc;

import java.lang.reflect.Field;

import java.util.Iterator;

import java.rmi.RemoteException;
import java.rmi.ServerException;

import java.sql.PreparedStatement;

import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.plugins.jaws.JAWSPersistenceManager;
import org.jboss.ejb.plugins.jaws.JPMStoreEntityCommand;
import org.jboss.ejb.plugins.jaws.metadata.CMPFieldMetaData;

/**
 * JAWSPersistenceManager JDBCStoreEntityCommand
 *
 * @see <related>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Rickard �berg</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Joe Shevland</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Justin Forder</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Sebastien
Alborini</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Vinay Menon</a>
 * @version $Revision: 1.7 $
 */
public class JDBCStoreEntityCommand
   extends JDBCUpdateCommand
   implements JPMStoreEntityCommand
{
   // Constructors --------------------------------------------------

   public JDBCStoreEntityCommand(JDBCCommandFactory factory)
   {
      super(factory, "Store");
      boolean tuned = jawsEntity.hasTunedUpdates();

      // If we don't have tuned updates, create static SQL
      if (!tuned)
      {
         setSQL(makeSQL(null));
      }
   }

   // JPMStoreEntityCommand implementation ---------------------------

   /**
    * if the readOnly flag is specified in the xml file this won't
store.
    * if not a tuned or untuned update is issued.
    */
   public void execute(EntityEnterpriseContext ctx)
      throws RemoteException
   {
      // Check for read-only
      // JF: Shouldn't this throw an exception?
      if (jawsEntity.isReadOnly())
      {
         return;
      }

      ExecutionState es = new ExecutionState();
      es.ctx = ctx;
      es.currentState = getState(ctx);
      boolean dirty = false;


      boolean tuned = jawsEntity.hasTunedUpdates();

      // For tuned updates, need to see which fields have changed

      if (tuned)
      {
         es.dirtyField = new boolean[es.currentState.length];
         Object[] oldState =
           
((JAWSPersistenceManager.PersistenceContext)ctx.getPersistenceContext()).state;

         for (int i = 0; i < es.currentState.length; i++)
         {
            es.dirtyField[i] = changed(es.currentState[i], oldState[i]);
            dirty |= es.dirtyField[i];
         }
      }

      if (!tuned || dirty)
      {
         try
         {
            // Update db
            jdbcExecute(es);

         } catch (Exception e)
         {
            throw new ServerException("Store failed", e);
         }
      }
   }

   // JDBCUpdateCommand overrides -----------------------------------

   /**
    * Returns dynamically-generated SQL if this entity
    * has tuned updates, otherwise static SQL.
    */
   protected String getSQL(Object argOrArgs) throws Exception
   {
      boolean tuned = jawsEntity.hasTunedUpdates();

      String sql =  tuned ? makeSQL(argOrArgs) :
super.getSQL(argOrArgs);
      return sql;
   }

   protected void setParameters(PreparedStatement stmt, Object
argOrArgs)
      throws Exception
   {
      ExecutionState es = (ExecutionState)argOrArgs;
      boolean tuned = jawsEntity.hasTunedUpdates();

      int idx = 1;
      Iterator iter = jawsEntity.getCMPFields();
      int i = 0;

      //Modified by Vinay Menon  - Start
      String stableRowIdColumn = jawsEntity.getStableRowIdColumn();

      /**
       * Will store the actual value for the stable row id column
       * and the JDBC type for this column
       */
      Object stableRowIdColumnValue=null;
      int stableRowIdColumnType=0;

      while (iter.hasNext())
      {
         CMPFieldMetaData cmpField = (CMPFieldMetaData)iter.next();

         /**
          * If the stable row id column was specified in jaws.xml and
the current
          * column being processed is the stable rowid coulmn, then save
the value
          * and datatype as we will need it to set the parameters in the
WHERE
          * clause
          */
         if(stableRowIdColumn!=null &&
cmpField.getColumnName().equalsIgnoreCase(stableRowIdColumn))
         {
            stableRowIdColumnValue = es.currentState[i];
            stableRowIdColumnType = cmpField.getJDBCType();

            System.out.println(" -- Stable RowID is "+
stableRowIdColumnValue +" -- ");
            if(stableRowIdColumnValue == null)
            {
                String sql = makeSQL(argOrArgs,true);
                stmt = stmt.getConnection().prepareStatement(sql);
                setParameters(stmt,argOrArgs);
                return;
            }
         }
         else
         {
             if (!tuned || es.dirtyField[i])
             {
                setParameter(stmt, idx++, cmpField.getJDBCType(),
es.currentState[i]);
             }
         }

         i++;
      }

      /**
       * Alright, we've set all the parameters now and lets set the
parameters for
       * the WHERE clause. If the stable row id was specified in the
jaws.xml
       * then set the parameter for that alone, else set the usual
primary key
       * parameters to update based on that.
       */
      if(stableRowIdColumn!=null)
      {
         
setParameter(stmt,idx,stableRowIdColumnType,stableRowIdColumnValue);
      }
      else
      {
          setPrimaryKeyParameters(stmt, idx, es.ctx.getId());
      }
      //Modified by Vinay Menon  - End
   }

   protected Object handleResult(int rowsAffected, Object argOrArgs)
      throws Exception
   {
      ExecutionState es = (ExecutionState)argOrArgs;
      boolean tuned = jawsEntity.hasTunedUpdates();

      if (tuned)
      {
         // Save current state for tuned updates
         JAWSPersistenceManager.PersistenceContext pCtx =
           
(JAWSPersistenceManager.PersistenceContext)es.ctx.getPersistenceContext();
         pCtx.state = es.currentState;
      }

      return null;
   }

   // Protected -----------------------------------------------------

   protected final boolean changed(Object current, Object old)
   {
      return (current == null) ? (old != null) : (old == null ? true :
!current.equals(old));
   }

   protected String makeSQL(Object argOrArgs)
   {
        return makeSQL(argOrArgs,false);
   }

   /**
    * Used to create static SQL (tuned = false) or dynamic SQL (tuned =
true).
    */
   private String makeSQL(Object argOrArgs,boolean overrideRowId)
   {
      ExecutionState es = (ExecutionState)argOrArgs;  // NB: null if
tuned
      boolean tuned = jawsEntity.hasTunedUpdates();

      //Modified by Vinay Menon  - Start
      String stableRowIdColumn = jawsEntity.getStableRowIdColumn();
      if(stableRowIdColumn==null)
      {
        /**
         * If it isn't there then just set it to an empty string to
avoid checking
         * for null in a loop.
         */
        stableRowIdColumn = "";
      }

      String sql = "UPDATE "+jawsEntity.getTableName()+" SET ";
      Iterator iter = jawsEntity.getCMPFields();
      int i = 0;
      boolean first = true;
      while (iter.hasNext())
      {
         CMPFieldMetaData cmpField = (CMPFieldMetaData)iter.next();

        
if(!(cmpField.getColumnName().equalsIgnoreCase(stableRowIdColumn) ||
cmpField.getName().equalsIgnoreCase(stableRowIdColumn)))
         {
             if (!tuned || es.dirtyField[i++])
             {
                sql += (first?"":",") +
                   cmpField.getColumnName() + "=?";
                first = false;
             }
        }
      }

      sql += " WHERE ";

      //Construct the WHERE clause - either based on the stable row id
or the PK
      if(stableRowIdColumn.trim().length()>1 && (!overrideRowId))
      {
          sql += stableRowIdColumn+" =?";
      }
      else
      {
        sql += getPkColumnWhereList();
      }
      //Modified by Vinay Menon  - End

      return sql;
   }

   // Inner Classes -------------------------------------------------

   protected static class ExecutionState
   {
      public EntityEnterpriseContext ctx;
      public Object[] currentState;
      public boolean[] dirtyField;    // only used for tuned updates
   }
}


4. Modified JDBCRemoveEntityCommand as follows,

/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.ejb.plugins.jaws.jdbc;

import java.rmi.RemoteException;
import java.util.Iterator;
import java.sql.PreparedStatement;

import javax.ejb.RemoveException;

import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.plugins.jaws.JPMRemoveEntityCommand;
import org.jboss.ejb.plugins.jaws.metadata.CMPFieldMetaData;

/**
 * JAWSPersistenceManager JDBCRemoveEntityCommand
 *
 * @see <related>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Rickard �berg</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Joe Shevland</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Justin Forder</a>
 * @author <a href="mailto:[EMAIL PROTECTED]";>Vinay Menon</a>
 * @version $Revision: 1.5 $
 */
public class JDBCRemoveEntityCommand
   extends JDBCUpdateCommand
   implements JPMRemoveEntityCommand
{
   // Constructors --------------------------------------------------

   public JDBCRemoveEntityCommand(JDBCCommandFactory factory)
   {
      super(factory, "Remove");


      //Modified by Vinay Menon  - Start
      String stableRowIdColumn = jawsEntity.getStableRowIdColumn();

      String sql;

      /**
       * If the stable rowid column was specified in the jaws.xml then
use it
       * for delete operations. Else use the standard PK based delete.
       */
      if(stableRowIdColumn!=null)
      {
          // Remove SQL
          sql = "DELETE FROM " + jawsEntity.getTableName() +" WHERE
"+stableRowIdColumn+"=?";
      }
      else
      {
          // Remove SQL
          sql = "DELETE FROM " + jawsEntity.getTableName() +
                       " WHERE "+getPkColumnWhereList();
      }
      //Modified by Vinay Menon  - End

      setSQL(sql);
   }

   // JPMRemoveEntityCommand implementation -------------------------

   public void execute(EntityEnterpriseContext ctx)
      throws RemoteException, RemoveException
   {
      try
      {
         // Remove from DB
         jdbcExecute(ctx);
      } catch (Exception e)
      {
         throw new RemoveException("Could not remove "+ctx.getId());
      }
   }

   // JDBCUpdateCommand overrides -----------------------------------

   protected void setParameters(PreparedStatement stmt, Object
argOrArgs)
      throws Exception
   {
      EntityEnterpriseContext ctx = (EntityEnterpriseContext)argOrArgs;

      ExecutionState es = (ExecutionState)argOrArgs;

      //Modified by Vinay Menon  - Start
      String stableRowIdColumn = jawsEntity.getStableRowIdColumn();

      int i=0;

      //If the stable rowid coulumn was specified get its value and set
param
      if(stableRowIdColumn!=null )
      {
          Iterator iter = jawsEntity.getCMPFields();
          while (iter.hasNext())
          {
             CMPFieldMetaData cmpField = (CMPFieldMetaData)iter.next();

            
if(cmpField.getColumnName().equalsIgnoreCase(stableRowIdColumn))
             {
                setParameter(stmt, 1, cmpField.getJDBCType(),
es.currentState[i]);
             }

             i++;
          }
      }
      //Else just use the standard PK values
      else
      {
        setPrimaryKeyParameters(stmt, 1, ctx.getId());
      }
      //Modified by Vinay Menon  - End
   }

   protected Object handleResult(int rowsAffected, Object argOrArgs)
      throws Exception
   {
      if (rowsAffected == 0)
      {
         throw new RemoveException("Could not remove entity");
      }
      return null;
   }

   // Inner Classes -------------------------------------------------

   protected static class ExecutionState
   {
      public EntityEnterpriseContext ctx;
      public Object[] currentState;
      public boolean[] dirtyField;    // only used for tuned updates
   }
}

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to