Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2002, 2013 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  
  package com.sleepycat.persist;
  
 import java.util.List;
 
 /* <!-- begin JE only --> */
 /* <!-- end JE only --> */
Performs an equality join on two or more secondary keys.

EntityJoin objects are thread-safe. Multiple threads may safely call the methods of a shared EntityJoin object.

An equality join is a match on all entities in a given primary index that have two or more specific secondary key values. Note that key ranges may not be matched by an equality join, only exact keys are matched.

For example:

  // Index declarations -- see href="package-summary.html.example">package summary example.
  //
  PrimaryIndex<String, Person> personBySsn;
  SecondaryIndex<String, String, Person> personByParentSsn;
  SecondaryIndex<Long, String, Person> personByEmployerIds;
  Employer employer = ...;

  // Match on all Person objects having parentSsn "111-11-1111" and also
  // containing an employerId of employer.id.  In other words, match on all
  // of Bob's children that work for a given employer.
  //
  EntityJoin<String, Person> join = new EntityJoin(personBySsn);
  join.addCondition(personByParentSsn, "111-11-1111");
  join.addCondition(personByEmployerIds, employer.id);

  // Perform the join operation by traversing the results with a cursor.
  //
  ForwardCursor<Person> results = join.entities();
  try {
      for (Person person : results) {
          System.out.println(person.ssn + ' ' + person.name);
      }
  } finally {
      results.close();
  }

Author(s):
Mark Hayes
 
 public class EntityJoin<PK, E> {
 
     private PrimaryIndex<PK, E> primary;
     private List<Conditionconditions;

    
Creates a join object for a given primary index.

Parameters:
index the primary index on which the join will operate.
 
     public EntityJoin(PrimaryIndex<PK, E> index) {
          = index;
          = new ArrayList<Condition>();
     }

    
Adds a secondary key condition to the equality join. Only entities having the given key value in the given secondary index will be returned by the join operation.

Parameters:
index the secondary index containing the given key value.
key the key value to match during the join.
 
     public <SK> void addCondition(SecondaryIndex<SK, PK, E> index, SK key) {
 
         /* Make key entry. */
         DatabaseEntry keyEntry = new DatabaseEntry();
         index.getKeyBinding().objectToEntry(keykeyEntry);
 
        /* Use keys database if available. */
        Database db = index.getKeysDatabase();
        if (db == null) {
            db = index.getDatabase();
        }
        /* Add condition. */
        .add(new Condition(dbkeyEntry));
    }

    
Opens a cursor that returns the entities qualifying for the join. The join operation is performed as the returned cursor is accessed.

The operations performed with the cursor will not be transaction protected, and com.sleepycat.je.CursorConfig.DEFAULT is used implicitly.

Returns:
the cursor.
Throws:
com.sleepycat.je.OperationFailureException if one of the Read Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if less than two conditions were added.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public ForwardCursor<E> entities()
        throws DatabaseException {
        return entities(nullnull);
    }

    
Opens a cursor that returns the entities qualifying for the join. The join operation is performed as the returned cursor is accessed.

Parameters:
txn the transaction used to protect all operations performed with the cursor, or null if the operations should not be transaction protected. If the store is non-transactional, null must be specified. For a transactional store the transaction is optional for read-only access and required for read-write access.
config the cursor configuration that determines the default lock mode used for all cursor operations, or null to implicitly use com.sleepycat.je.CursorConfig.DEFAULT.
Returns:
the cursor.
Throws:
com.sleepycat.je.OperationFailureException if one of the Read Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if less than two conditions were added.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public ForwardCursor<E> entities(Transaction txnCursorConfig config)
        throws DatabaseException {
        return new JoinForwardCursor<E>(txnconfigfalse);
    }

    
Opens a cursor that returns the primary keys of entities qualifying for the join. The join operation is performed as the returned cursor is accessed.

The operations performed with the cursor will not be transaction protected, and com.sleepycat.je.CursorConfig.DEFAULT is used implicitly.

Returns:
the cursor.
Throws:
com.sleepycat.je.OperationFailureException if one of the Read Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if less than two conditions were added.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public ForwardCursor<PK> keys()
        throws DatabaseException {
        return keys(nullnull);
    }

    
Opens a cursor that returns the primary keys of entities qualifying for the join. The join operation is performed as the returned cursor is accessed.

Parameters:
txn the transaction used to protect all operations performed with the cursor, or null if the operations should not be transaction protected. If the store is non-transactional, null must be specified. For a transactional store the transaction is optional for read-only access and required for read-write access.
config the cursor configuration that determines the default lock mode used for all cursor operations, or null to implicitly use com.sleepycat.je.CursorConfig.DEFAULT.
Returns:
the cursor.
Throws:
com.sleepycat.je.OperationFailureException if one of the Read Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if less than two conditions were added.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public ForwardCursor<PK> keys(Transaction txnCursorConfig config)
        throws DatabaseException {
        return new JoinForwardCursor<PK>(txnconfigtrue);
    }
    private static class Condition {
        private Database db;
        private DatabaseEntry key;
        Condition(Database dbDatabaseEntry key) {
            this. = db;
            this. = key;
        }
        Cursor openCursor(Transaction txnCursorConfig config)
            throws DatabaseException {
            OperationStatus status;
            Cursor cursor = .openCursor(txnconfig);
            try {
                DatabaseEntry data = .;
                status = cursor.getSearchKey(datanull);
            } catch (DatabaseException e) {
                try {
                    cursor.close();
                } catch (DatabaseException ignored) {}
                throw e;
            }
            if (status == .) {
                return cursor;
            } else {
                cursor.close();
                return null;
            }
        }
    }
    private class JoinForwardCursor<V> implements ForwardCursor<V> {
        private Cursor[] cursors;
        private JoinCursor joinCursor;
        private boolean doKeys;
        JoinForwardCursor(Transaction txnCursorConfig configboolean doKeys)
            throws DatabaseException {
            this. = doKeys;
            try {
                 = new Cursor[.size()];
                for (int i = 0; i < .i += 1) {
                    Condition cond = .get(i);
                    Cursor cursor = cond.openCursor(txnconfig);
                    if (cursor == null) {
                        /* Leave joinCursor null. */
                        doClose(null);
                        return;
                    }
                    [i] = cursor;
                }
                 = .getDatabase().join(null);
            } catch (DatabaseException e) {
                /* doClose will throw e. */
                doClose(e);
            }
        }
        public V next()
            throws DatabaseException {
            return next(null);
        }
        public V next(LockMode lockMode)
            throws DatabaseException {
            if ( == null) {
                return null;
            }
            if () {
                DatabaseEntry key = new DatabaseEntry();
                OperationStatus status = .getNext(keylockMode);
                if (status == .) {
                    EntryBinding binding = .getKeyBinding();
                    return (V) binding.entryToObject(key);
                }
            } else {
                DatabaseEntry key = new DatabaseEntry();
                DatabaseEntry data = new DatabaseEntry();
                OperationStatus status =
                    .getNext(keydatalockMode);
                if (status == .) {
                    EntityBinding binding = .getEntityBinding();
                    return (V) binding.entryToObject(keydata);
                }
            }
            return null;
        }
        public Iterator<V> iterator() {
            return iterator(null);
        }
        public Iterator<V> iterator(LockMode lockMode) {
            return new BasicIterator<V>(thislockMode);
        }
        public void close()
            throws DatabaseException {
            doClose(null);
        }
        private void doClose(DatabaseException firstException)
            throws DatabaseException {
            if ( != null) {
                try {
                    .close();
                     = null;
                } catch (DatabaseException e) {
                    if (firstException == null) {
                        firstException = e;
                    }
                }
            }
            for (int i = 0; i < .i += 1) {
                Cursor cursor = [i];
                if (cursor != null) {
                    try {
                        cursor.close();
                        [i] = null;
                    } catch (DatabaseException e) {
                        if (firstException == null) {
                            firstException = e;
                        }
                    }
                }
            }
            if (firstException != null) {
                throw firstException;
            }
        }
    }
New to GrepCode? Check out our FAQ X