User: dsundstrom
  Date: 02/01/15 14:34:18

  Modified:    src/main/org/jboss/ejb/plugins/cmp/jdbc
                        JDBCLoadRelationCommand.java
  Log:
  Added support for readahead and preload.
  
  Merged functions from JDBCFindByForeignKey.
  
  Converted field arrays to lists.
  
  Revision  Changes    Path
  1.11      +304 -49   
jboss/src/main/org/jboss/ejb/plugins/cmp/jdbc/JDBCLoadRelationCommand.java
  
  Index: JDBCLoadRelationCommand.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/cmp/jdbc/JDBCLoadRelationCommand.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- JDBCLoadRelationCommand.java      2002/01/05 12:08:51     1.10
  +++ JDBCLoadRelationCommand.java      2002/01/15 22:34:17     1.11
  @@ -10,28 +10,39 @@
   import java.sql.Connection;
   import java.sql.PreparedStatement; 
   import java.sql.ResultSet; 
  -import java.util.HashSet; 
  -import java.util.Set; 
  +import java.util.ArrayList; 
  +import java.util.Collection;
  +import java.util.Collections;
  +import java.util.Iterator; 
  +import java.util.HashMap; 
  +import java.util.List; 
  +import java.util.Map; 
   import javax.ejb.EJBException; 
   
  +import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge; 
   import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge; 
   import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMRFieldBridge; 
  +import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge; 
   import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
  +import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationMetaData;
   import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCTypeMappingMetaData;
   import org.jboss.logging.Logger;
  +import org.jboss.util.FinderResults;
   
   /**
    * Loads relations for a particular entity from a relation table.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Dain Sundstrom</a>
  - * @version $Revision: 1.10 $
  + * @version $Revision: 1.11 $
    */
   public class JDBCLoadRelationCommand {
  -   private JDBCStoreManager manager;
  -   private Logger log;
  +   private final JDBCStoreManager manager;
  +   private final JDBCEntityBridge entity;
  +   private final Logger log;
   
      public JDBCLoadRelationCommand(JDBCStoreManager manager) {
         this.manager = manager;
  +      this.entity = manager.getEntityBridge();
   
         // Create the Log
         log = Logger.getLogger(
  @@ -40,38 +51,22 @@
               manager.getMetaData().getName());
      }
   
  -   public Set execute(JDBCCMRFieldBridge cmrField, Object pk) {
  -      // get the key fields
  -      JDBCCMPFieldBridge[] myKeyFields = cmrField.getTableKeyFields();
  -      JDBCCMPFieldBridge[] relatedKeyFields = 
  -            cmrField.getRelatedCMRField().getTableKeyFields();
  -
  -      // generate SQL
  -      StringBuffer sql = new StringBuffer();
  -      String columnNamesClause = 
SQLUtil.getColumnNamesClause(cmrField.getRelatedCMRField().getTableKeyFields());
  -      String tableName = cmrField.getRelationMetaData().getTableName();
  -      String whereClause = SQLUtil.getWhereClause(cmrField.getTableKeyFields());
  -
  -      if (cmrField.getRelationMetaData().hasRowLocking())
  -      {
  -         JDBCFunctionMappingMetaData rowLocking = 
manager.getMetaData().getTypeMapping().getRowLockingTemplate();
  -         if (rowLocking == null)
  -         {
  -            throw new IllegalStateException("row-locking is not allowed for this 
type of datastore");
  -         }
  -         else
  -         {
  -            String[] args = new String[] {columnNamesClause, tableName, 
whereClause};
  -            sql.append(rowLocking.getFunctionSql(args));
  -         }
  -      }
  -      else
  -      {
  -         sql.append("SELECT ").append(columnNamesClause);
  -         sql.append(" FROM ").append(tableName);
  -         sql.append(" WHERE ").append(whereClause);
  -      }
  +   public Collection execute(JDBCCMRFieldBridge cmrField, Object pk) {
  +      JDBCCMRFieldBridge relatedCMRField = cmrField.getRelatedCMRField();
   
  +      // get the read ahead cahces
  +      ReadAheadCache readAheadCache = manager.getReadAheadCache();
  +      ReadAheadCache relatedReadAheadCache = 
  +            cmrField.getRelatedManager().getReadAheadCache();
  +      
  +      // get the finder results associated with this context, if it exists
  +      ReadAheadCache.EntityReadAheadInfo info = 
  +            readAheadCache.getEntityReadAheadInfo(pk);
  +      List loadKeys = info.getLoadKeys();
  +
  +      // generate the sql
  +      String sql = getSQL(cmrField, loadKeys.size());
  +  
         Connection con = null;
         PreparedStatement ps = null;
         try {
  @@ -79,39 +74,299 @@
            con = cmrField.getRelationMetaData().getDataSource().getConnection();
            
            // create the statement
  -         if (log.isDebugEnabled())
  -            log.debug("Executing SQL: " + sql);
  +         log.debug("Executing SQL: " + sql);
            ps = con.prepareStatement(sql.toString());
            
  +         // get the load fields
  +         List myKeyFields = getMyKeyFields(cmrField);
  +         List relatedKeyFields = getRelatedKeyFields(cmrField);
  +         List preloadFields = getPreloadFields(cmrField);
  +         
            // set the parameters
  -         int index = 1;
  -         for(int i=0; i<myKeyFields.length; i++) {
  -            index = myKeyFields[i].setPrimaryKeyParameters(ps, index, pk);
  +         int paramIndex = 1;
  +         for(Iterator iter = loadKeys.iterator(); iter.hasNext();) {
  +            Object key = iter.next();
  +            for(Iterator fields = myKeyFields.iterator(); fields.hasNext(); ) {
  +               JDBCCMPFieldBridge field = (JDBCCMPFieldBridge)fields.next();
  +               paramIndex = field.setPrimaryKeyParameters(ps, paramIndex, key);
  +            }
            }
   
            // execute statement
            ResultSet rs = ps.executeQuery();
   
  +         // initialize the results map
  +         Map resultsMap = new HashMap(loadKeys.size());
  +         for(Iterator iter = loadKeys.iterator(); iter.hasNext();) {
  +            resultsMap.put(iter.next(), new ArrayList());
  +         }
  +
            // load the results
  -         Set result = new HashSet();   
  -         Object[] pkRef = new Object[1];
  +         Object[] ref = new Object[1];
            while(rs.next()) {
  -            pkRef[0] = null;   
  -            index = 1;
  -            for(int i=0; i<relatedKeyFields.length; i++) {
  -               index = relatedKeyFields[i].loadPrimaryKeyResults(
  -                     rs, index, pkRef);
  +            // reset the column index for this row
  +            int index = 1;
  +
  +            // ref must be reset to null before each load
  +            ref[0] = null;
  +
  +            // if we are loading more then one entity, load the pk from the row
  +            Object loadedPk = pk;
  +            if(loadKeys.size() > 1) {
  +               // load the pk
  +               for(Iterator fields=myKeyFields.iterator(); fields.hasNext();) {
  +                  JDBCCMPFieldBridge field = (JDBCCMPFieldBridge)fields.next();
  +                  index = field.loadPrimaryKeyResults(rs, index, ref);
  +               }      
  +               loadedPk = ref[0];
  +            }
  + 
  +            // load the fk
  +            ref[0] = null;
  +            for(Iterator fields = relatedKeyFields.iterator();
  +                     fields.hasNext();) {
  +               JDBCCMPFieldBridge field = (JDBCCMPFieldBridge)fields.next();
  +               index = field.loadPrimaryKeyResults(rs, index, ref);
               }      
  -            result.add(pkRef[0]);
  +            Object loadedFk = ref[0];
  +   
  +            if(loadedFk != null) {
  +               // add this value to the list for loadedPk
  +               List results = (List)resultsMap.get(loadedPk);
  +               results.add(loadedFk);
  +
  +               // if the related cmr field is single valued we can pre-load
  +               // the reverse relationship
  +               if(relatedCMRField.isSingleValued()) {
  +                  relatedReadAheadCache.addPreloadData(
  +                        loadedFk,
  +                        relatedCMRField,
  +                        Collections.singletonList(loadedPk));
  +               }
  +
  +               // read the preload fields
  +               for(Iterator iter=preloadFields.iterator(); iter.hasNext();) {
  +                  JDBCFieldBridge field = (JDBCFieldBridge)iter.next();
  +                  ref[0] = null;
  +
  +                  // read the value and store it in the readahead cache
  +                  index = field.loadArgumentResults(rs, index, ref);
  +                  relatedReadAheadCache.addPreloadData(loadedFk, field, ref[0]);
  +               }
  +            }
            }
   
  +         // set all of the preloaded values
  +         for(Iterator iter=resultsMap.keySet().iterator(); iter.hasNext();) {
  +            Object key = iter.next();
  +            if(!key.equals(pk)) {
  +               readAheadCache.addPreloadData(
  +                     key, cmrField, (List)resultsMap.get(key));
  +            }
  +         }
  +
  +         // get the real result list
  +         List result = (List)resultsMap.get(pk);
  +
  +         // Convert the pk collection into finder results
  +         FinderResults finderResults = new FinderResults(
  +               result, null, null, null);
  +
  +         // add results to the cache
  +         if(!cmrField.getReadAhead().isNone()) {
  +            relatedReadAheadCache.addFinderResult(finderResults);
  +         }
  +
            // success
            return result;
  +      } catch(EJBException e) {
  +         throw e;
         } catch(Exception e) {
  -         throw new EJBException("Load relation by foreign-key failed", e);
  +         throw new EJBException("Load relation failed", e);
         } finally {
            JDBCUtil.safeClose(ps);
            JDBCUtil.safeClose(con);
         }
  +   }
  +
  +   private String getSQL(JDBCCMRFieldBridge cmrField, int keyCount) {
  +
  +      List myKeyFields = getMyKeyFields(cmrField);
  +      List relatedKeyFields = getRelatedKeyFields(cmrField);
  +      List preloadFields = getPreloadFields(cmrField);
  +      String relationTable = getRelationTable(cmrField);
  +      String relatedTable = cmrField.getRelatedEntity().getTableName();
  +      
  +      // do we need to join the relation table and the related table
  +      boolean join = (preloadFields.size() > 0 && 
  +            !relationTable.equals(relatedTable));
  +
  +      // aliases for the tables, only required if we are joining the tables
  +      String relationTableAlias = "";
  +      String relatedTableAlias = "";
  +      if(join) {
  +         relationTableAlias = relationTable;
  +         relatedTableAlias = relatedTable;
  +      }
  +
  +      //
  +      // column names clause
  +      // 
  +      StringBuffer columnNamesClause = new StringBuffer();
  +      if(keyCount > 1) {
  +         columnNamesClause.append(
  +               SQLUtil.getColumnNamesClause(myKeyFields, relationTableAlias));
  +         columnNamesClause.append(", ");
  +      }
  +      columnNamesClause.append(
  +            SQLUtil.getColumnNamesClause(relatedKeyFields, relationTableAlias));
  +      if(preloadFields.size() > 0) {
  +         columnNamesClause.append(", ");
  +         columnNamesClause.append(
  +               SQLUtil.getColumnNamesClause(preloadFields, relatedTableAlias));
  +      }
  +
  +      //
  +      // from clause
  +      //
  +      StringBuffer fromClause = new StringBuffer();
  +      fromClause.append(relationTable);
  +      if(join) {
  +         fromClause.append(", ").append(relatedTable);
  +      }
  +
  +      //
  +      // where clause
  +      // 
  +      StringBuffer whereClause = new StringBuffer();
  +      // add the join 
  +      if(join) {
  +         // join the tables
  +         whereClause.append("(");
  +         whereClause.append(SQLUtil.getJoinClause(
  +                  relatedKeyFields,
  +                  relationTable,
  +                  cmrField.getRelatedEntity().getPrimaryKeyFields(),
  +                  relatedTable));
  +         whereClause.append(") AND (");
  +      }
  +      // add the keys 
  +      String pkWhere = SQLUtil.getWhereClause(myKeyFields, relationTableAlias);
  +      for(int i=0; i<keyCount; i++) {
  +         if(i > 0) {
  +            whereClause.append(" OR ");
  +         }
  +         whereClause.append("(").append(pkWhere).append(")");
  +      }
  +      if(join) {
  +         whereClause.append(")");
  +      }
  +      
  +      //
  +      // assemble pieces into final statement
  +      //
  +      JDBCFunctionMappingMetaData selectTemplate = getSelectTemplate(cmrField);
  +      if(selectTemplate != null) {
  +         String[] args = new String[] {
  +               columnNamesClause.toString(),
  +               fromClause.toString(),
  +               whereClause.toString()};
  +         return selectTemplate.getFunctionSql(args);
  +      } else {
  +         StringBuffer sql = new StringBuffer(
  +               7 + columnNamesClause.length() +
  +               6 + fromClause.length() +
  +               7 + whereClause.length());
  +
  +         sql.append("SELECT ").append(columnNamesClause);
  +         sql.append(" FROM ").append(fromClause);
  +         sql.append(" WHERE ").append(whereClause);
  +         return sql.toString();
  +      }
  +   }
  +
  +   private List getMyKeyFields(JDBCCMRFieldBridge cmrField) {
  +      if(cmrField.getRelationMetaData().isTableMappingStyle()) {
  +         // relation table
  +         return cmrField.getTableKeyFields();
  +      } else if(cmrField.getRelatedCMRField().hasForeignKey()) {
  +         // related has foreign key
  +         return cmrField.getRelatedCMRField().getForeignKeyFields();
  +      } else {
  +         // i have foreign key
  +         return entity.getPrimaryKeyFields();
  +      }
  +   }
  + 
  +   private List getRelatedKeyFields(JDBCCMRFieldBridge cmrField) {
  +      if(cmrField.getRelationMetaData().isTableMappingStyle()) {
  +         // relation table
  +         return cmrField.getRelatedCMRField().getTableKeyFields();
  +      } else if(cmrField.getRelatedCMRField().hasForeignKey()) {
  +         // related has foreign key
  +         return cmrField.getRelatedEntity().getPrimaryKeyFields();
  +      } else {
  +         // i have foreign key
  +         return cmrField.getForeignKeyFields();
  +      }
  +   } 
  +
  +   private List getPreloadFields(JDBCCMRFieldBridge cmrField) {
  +      if(!cmrField.getReadAhead().isOnFind()) {
  +         return Collections.EMPTY_LIST;
  +      }
  +      String eagerLoadGroup = cmrField.getReadAhead().getEagerLoadGroup();
  +      return cmrField.getRelatedEntity().getLoadGroup(eagerLoadGroup);
  +   }
  +
  +   private String getRelationTable(JDBCCMRFieldBridge cmrField) {
  +      if(cmrField.getRelationMetaData().isTableMappingStyle()) {
  +         // relation table
  +         return cmrField.getRelationMetaData().getTableName();
  +      } else if(cmrField.getRelatedCMRField().hasForeignKey()) {
  +         // related has foreign key
  +         return cmrField.getRelatedEntity().getTableName();
  +      } else {
  +         // i have foreign key
  +         return entity.getTableName();
  +      }
  +   }
  +
  +   private JDBCFunctionMappingMetaData getSelectTemplate(
  +         JDBCCMRFieldBridge cmrField) {
  +
  +      JDBCFunctionMappingMetaData selectTemplate = null;
  +      if(cmrField.getRelationMetaData().isTableMappingStyle()) {
  +         // relation table
  +         if(cmrField.getRelationMetaData().hasRowLocking()) {
  +            selectTemplate =
  +               
cmrField.getRelationMetaData().getTypeMapping().getRowLockingTemplate();
  +            if(selectTemplate == null) {
  +               throw new IllegalStateException("row-locking is not allowed " +
  +                     "for this type of datastore");
  +            }
  +         }
  +      } else if(cmrField.getRelatedCMRField().hasForeignKey()) {
  +         // related has foreign key
  +         if(cmrField.getRelatedEntity().getMetaData().hasRowLocking()) {
  +            selectTemplate =
  +               
cmrField.getRelatedEntity().getMetaData().getTypeMapping().getRowLockingTemplate();
  +            if(selectTemplate == null) {
  +               throw new IllegalStateException("row-locking is not allowed " +
  +                     "for this type of datastore");
  +            }
  +         }
  +      } else {
  +         // i have foreign key
  +         if(entity.getMetaData().hasRowLocking()) {
  +            selectTemplate =
  +               entity.getMetaData().getTypeMapping().getRowLockingTemplate();
  +            if(selectTemplate == null) {
  +               throw new IllegalStateException("row-locking is not allowed " +
  +                     "for this type of datastore");
  +            }
  +         }
  +      }
  +      return selectTemplate;
      }
   }
  
  
  

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

Reply via email to