SecondaryDatabase (Oracle - Berkeley DB Java Edition API)
Date: 2014-12-16

com.sleepycat.je

## Class SecondaryDatabase

- java.lang.Object
- - com.sleepycat.je.Database
  - - com.sleepycat.je.SecondaryDatabase

- All Implemented Interfaces:
    Closeable, AutoCloseable

      public class SecondaryDatabase
      extends Database

  A secondary database handle.

  Secondary databases are opened with `Environment.openSecondaryDatabase` and are always associated with a single primary database. The distinguishing characteristics of a secondary database are:

  - Records are automatically added to a secondary database when records are added, modified and deleted in the primary database. Direct calls to `put()` methods on a secondary database are prohibited.
  - The `delete` method of a secondary database will delete the primary record and as well as all its associated secondary records.
  - Calls to all `get()` methods will return the data from the associated primary database.
  - Additional `get()` method signatures are provided to return the primary key in an additional `pKey` parameter.
  - Calls to `openCursor` will return a `SecondaryCursor`, which itself has `get()` methods that return the data of the primary database and additional `get()` method signatures for returning the primary key.

  Before opening or creating a secondary database you must implement the `SecondaryKeyCreator` or `SecondaryMultiKeyCreator` interface.

  For example, to create a secondary database that supports duplicates:

           Database primaryDb; // The primary database must already be open.
           SecondaryKeyCreator keyCreator; // Your key creator implementation.
           SecondaryConfig secConfig = new SecondaryConfig();
           secConfig.setAllowCreate(true);
           secConfig.setSortedDuplicates(true);
           secConfig.setKeyCreator(keyCreator);
           SecondaryDatabase newDb = env.openSecondaryDatabase(transaction,
                                                               "myDatabaseName",
                                                               primaryDb,
                                                               secConfig)

  If a primary database is to be associated with one or more secondary databases, it may not be configured for duplicates.

  WARNING: The associations between primary and secondary databases are not stored persistently. Whenever a primary database is opened for write access by the application, the appropriate associated secondary databases should also be opened by the application. This is necessary to ensure data integrity when changes are made to the primary database. If the secondary database is not opened, it will not be updated when the primary is updated, and the references between the databases will become invalid. (Note that this warning does not apply when using the `DPL`, which does store secondary relationships persistently.)

  ### Special considerations for using Secondary Databases with and without Transactions

  Normally, during a primary database write operation (insert, update or delete), all associated secondary databases are also updated. However, when an exception occurs during the write operation, the updates may be incomplete. If the databases are transactional, this is handled by aborting the transaction to undo the incomplete operation. If an auto-commit transaction is used (null is passed for the transaction), the transaction will be aborted automatically. If an explicit transaction is used, it must be aborted by the application caller after the exception is caught.

  However, if the databases are non-transactional, integrity problems can result when an exception occurs during the write operation. Because the write operation is not made atomic by a transaction, references between the databases will become invalid if the operation is incomplete. This results in a `SecondaryIntegrityException` when attempting to access the databases later.

  A secondary integrity problem is persistent; it cannot be resolved by reopening the databases or the environment. The only way to resolve the problem is to restore the environment from a valid backup, or, if the integrity of the primary database is assumed, to remove and recreate all secondary databases.

  Therefore, secondary databases and indexes should always be used in conjunction with transactional databases and stores. Without transactions, it is the responsibility of the application to handle the results of the incomplete write operation or to take steps to prevent this situation from happening in the first place.

  The following exceptions may be thrown during a write operation, and may cause an integrity problem in the absence of transactions.

  - `SecondaryConstraintException`, see its subclasses for more information.
  - `LockConflictException`, when more than one thread is accessing the databases.
  - `EnvironmentFailureException`, if an unexpected or system failure occurs.
  - There is always the possibility of an `Error` or an unintended `RuntimeException`.

- - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `close()` Closes a secondary database and dis-associates it from its primary database.
    `OperationStatus` | `delete(Transaction txn, DatabaseEntry key)` Deletes the primary key/data pair associated with the specified secondary key.
    `OperationStatus` | `get(Transaction txn, DatabaseEntry key, DatabaseEntry pKey, DatabaseEntry data, LockMode lockMode)` Retrieves the key/data pair with the given key.
    `OperationStatus` | `get(Transaction txn, DatabaseEntry key, DatabaseEntry data, LockMode lockMode)` Retrieves the key/data pair with the given key.
    `SecondaryConfig` | `getConfig()` Returns a copy of the secondary configuration of this database.
    `Database` | `getPrimaryDatabase()` Returns the primary database associated with this secondary database.
    `OperationStatus` | `getSearchBoth(Transaction txn, DatabaseEntry key, DatabaseEntry pKey, DatabaseEntry data, LockMode lockMode)` Retrieves the key/data pair with the specified secondary and primary key, that is, both the primary and secondary key items must match.
    `OperationStatus` | `getSearchBoth(Transaction txn, DatabaseEntry key, DatabaseEntry data, LockMode lockMode)` This operation is not allowed with this method signature.
    `SecondaryConfig` | `getSecondaryConfig()` Deprecated. As of JE 4.0.13, replaced by `getConfig()`.
    `List<SecondaryDatabase>` | `getSecondaryDatabases()` Returns an empty list, since this database is itself a secondary database.
    `JoinCursor` | `join(Cursor[] cursors, JoinConfig config)` This operation is not allowed on a secondary database.
    `SecondaryCursor` | `openCursor(Transaction txn, CursorConfig cursorConfig)` Obtain a cursor on a database, returning a `SecondaryCursor`.
    `SecondaryCursor` | `openSecondaryCursor(Transaction txn, CursorConfig cursorConfig)` Deprecated. As of JE 4.0.13, replaced by `openCursor(com.sleepycat.je.Transaction, com.sleepycat.je.CursorConfig)`.
    `OperationStatus` | `put(Transaction txn, DatabaseEntry key, DatabaseEntry data)` This operation is not allowed on a secondary database.
    `OperationStatus` | `putNoDupData(Transaction txn, DatabaseEntry key, DatabaseEntry data)` This operation is not allowed on a secondary database.
    `OperationStatus` | `putNoOverwrite(Transaction txn, DatabaseEntry key, DatabaseEntry data)` This operation is not allowed on a secondary database.

    - ### Methods inherited from class com.sleepycat.je.Database

      `compareDuplicates, compareKeys, count, count, getDatabaseName, getEnvironment, getStats, openCursor, openSequence, preload, preload, preload, removeSequence, sync, verify`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Method Detail

    - #### close

          public void close()
                     throws DatabaseException

      Closes a secondary database and dis-associates it from its primary database. A secondary database should be closed before closing its associated primary database. Discards the database handle.

      When closing the last open handle for a deferred-write database, any cached database information is flushed to disk as if `Database.sync()` were called.

      The database handle should not be closed while any other handle that refers to it is not yet closed; for example, database handles should not be closed while cursor handles into the database remain open, or transactions that include operations on the database have not yet been committed or aborted. Specifically, this includes `Cursor` and `Transaction` handles.

      When multiple threads are using the `Database` handle concurrently, only a single thread may call this method.

      When called on a database that is the primary database for a secondary index, the primary database should be closed only after all secondary indices which reference it have been closed.

      The database handle may not be accessed again after this method is called, regardless of the method's success or failure, with one exception: the `close` method itself may be called any number of times.

      WARNING: To guard against memory leaks, the application should discard all references to the closed handle. While BDB makes an effort to discard references from closed objects to the allocated memory for an environment, this behavior is not guaranteed. The safe course of action for an application is to discard all references to closed BDB objects.

      Specified by:
        `close` in interface `Closeable`
      Specified by:
        `close` in interface `AutoCloseable`
      Overrides:
        `close` in class `Database`
      Throws:
        `DatabaseException`
      See Also:
        `DatabaseConfig.setDeferredWrite`

    - #### getPrimaryDatabase

          public Database getPrimaryDatabase()

      Returns the primary database associated with this secondary database.
      Returns:
        the primary database associated with this secondary database.

    - #### getSecondaryDatabases

          public List<SecondaryDatabase> getSecondaryDatabases()

      Returns an empty list, since this database is itself a secondary database.
      Overrides:
        `getSecondaryDatabases` in class `Database`

    - #### getSecondaryConfig

          public SecondaryConfig getSecondaryConfig()
                                             throws DatabaseException

      Deprecated. As of JE 4.0.13, replaced by `getConfig()`.
      Returns a copy of the secondary configuration of this database.
      Returns:
        a copy of the secondary configuration of this database.
      Throws:
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `DatabaseException`

    - #### getConfig

          public SecondaryConfig getConfig()
                                    throws DatabaseException

      Returns a copy of the secondary configuration of this database.
      Overrides:
        `getConfig` in class `Database`
      Returns:
        a copy of the secondary configuration of this database.
      Throws:
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `DatabaseException`

    - #### openSecondaryCursor

          public SecondaryCursor openSecondaryCursor(Transaction txn,
                                            CursorConfig cursorConfig)
                                              throws DatabaseException

      Deprecated. As of JE 4.0.13, replaced by `openCursor(com.sleepycat.je.Transaction, com.sleepycat.je.CursorConfig)`.
      Obtain a cursor on a database, returning a `SecondaryCursor`. Calling this method is the equivalent of calling `openCursor(com.sleepycat.je.Transaction, com.sleepycat.je.CursorConfig)` and casting the result to `SecondaryCursor`.
      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 database is non-transactional, null must be specified. For a transactional database, the transaction is optional for read-only access and required for read-write access.
        `cursorConfig` - The cursor attributes. If null, default attributes are used.
      Returns:
        A secondary database cursor.
      Throws:
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `DatabaseException`

    - #### openCursor

          public SecondaryCursor openCursor(Transaction txn,
                                   CursorConfig cursorConfig)
                                     throws DatabaseException

      Obtain a cursor on a database, returning a `SecondaryCursor`.
      Overrides:
        `openCursor` in class `Database`
      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 database is non-transactional, null must be specified. For a transactional database, the transaction is optional for read-only access and required for read-write access.
        `cursorConfig` - The cursor attributes. If null, default attributes are used.
      Returns:
        A database cursor.
      Throws:
        `DatabasePreemptedException` - in a replicated environment if the master has truncated, removed or renamed the database.
        `OperationFailureException` - if this exception occurred earlier and caused the transaction to be invalidated.
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `DatabaseException`

    - #### delete

          public OperationStatus delete(Transaction txn,
                               DatabaseEntry key)
                                 throws DeleteConstraintException,
                                        LockConflictException,
                                        DatabaseException,
                                        UnsupportedOperationException,
                                        IllegalArgumentException

      Deletes the primary key/data pair associated with the specified secondary key. In the presence of duplicate key values, all primary records associated with the designated secondary key will be deleted. When the primary records are deleted, their associated secondary records are deleted as if `Database.delete(com.sleepycat.je.Transaction, com.sleepycat.je.DatabaseEntry)` were called. This includes, but is not limited to, the secondary record referenced by the given key.
      Overrides:
        `delete` in class `Database`
      Parameters:
        `key` - the secondary key used as input. It must be initialized with a non-null byte array by the caller.
        `txn` - For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
      Returns:
        The method will return `OperationStatus.NOTFOUND` if the specified key is not found in the database; otherwise the method will return `OperationStatus.SUCCESS`.
      Throws:
        `OperationFailureException` - if one of the Write Operation Failures occurs.
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `UnsupportedOperationException` - if this database is read-only.
        `IllegalArgumentException` - if an invalid parameter is specified.
        `DeleteConstraintException`
        `LockConflictException`
        `DatabaseException`

    - #### get

          public OperationStatus get(Transaction txn,
                            DatabaseEntry key,
                            DatabaseEntry data,
                            LockMode lockMode)
                              throws DatabaseException

      Description copied from class: `Database`
      Retrieves the key/data pair with the given key. If the matching key has duplicate values, the first data item in the set of duplicates is returned. Retrieval of duplicates requires the use of `Cursor` operations.
      Overrides:
        `get` in class `Database`
      Parameters:
        `key` - the secondary key used as input. It must be initialized with a non-null byte array by the caller.
        `data` - the primary data returned as output. Its byte array does not need to be initialized by the caller.
        `txn` - For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
        `lockMode` - the locking attributes; if null, default attributes are used.
      Returns:
        `OperationStatus.NOTFOUND` if no matching key/data pair is found; otherwise, `OperationStatus.SUCCESS`.
      Throws:
        `OperationFailureException` - if one of the Read Operation Failures occurs.
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `DatabaseException`

    - #### get

          public OperationStatus get(Transaction txn,
                            DatabaseEntry key,
                            DatabaseEntry pKey,
                            DatabaseEntry data,
                            LockMode lockMode)
                              throws DatabaseException

      Retrieves the key/data pair with the given key. If the matching key has duplicate values, the first data item in the set of duplicates is returned. Retrieval of duplicates requires the use of `Cursor` operations.
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
        `key` - the secondary key used as input. It must be initialized with a non-null byte array by the caller.
        `pKey` - the primary key returned as output. Its byte array does not need to be initialized by the caller.
        `data` - the primary data returned as output. Its byte array does not need to be initialized by the caller.
        `lockMode` - the locking attributes; if null, default attributes are used.
      Returns:
        `OperationStatus.NOTFOUND` if no matching key/data pair is found; otherwise, `OperationStatus.SUCCESS`.
      Throws:
        `OperationFailureException` - if one of the Read Operation Failures occurs.
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `IllegalStateException` - if the database has been closed.
        `IllegalArgumentException` - if an invalid parameter is specified.
        `DatabaseException`

    - #### getSearchBoth

          public OperationStatus getSearchBoth(Transaction txn,
                                      DatabaseEntry key,
                                      DatabaseEntry data,
                                      LockMode lockMode)
                                        throws UnsupportedOperationException

      This operation is not allowed with this method signature. `UnsupportedOperationException` will always be thrown by this method. The corresponding method with the `pKey` parameter should be used instead.
      Overrides:
        `getSearchBoth` in class `Database`
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
        `key` - the key used as input. It must be initialized with a non-null byte array by the caller.
        `data` - the data used as input. It must be initialized with a non-null byte array by the caller.
        `lockMode` - the locking attributes; if null, default attributes are used.
      Returns:
        `OperationStatus.NOTFOUND` if no matching key/data pair is found; otherwise, `OperationStatus.SUCCESS`.
      Throws:
        `UnsupportedOperationException`

    - #### getSearchBoth

          public OperationStatus getSearchBoth(Transaction txn,
                                      DatabaseEntry key,
                                      DatabaseEntry pKey,
                                      DatabaseEntry data,
                                      LockMode lockMode)
                                        throws DatabaseException

      Retrieves the key/data pair with the specified secondary and primary key, that is, both the primary and secondary key items must match.
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
        `key` - the secondary key used as input. It must be initialized with a non-null byte array by the caller.
        `pKey` - the primary key used as input. It must be initialized with a non-null byte array by the caller.
        `data` - the primary data returned as output. Its byte array does not need to be initialized by the caller.
        `lockMode` - the locking attributes; if null, default attributes are used.
      Returns:
        `OperationStatus.NOTFOUND` if no matching key/data pair is found; otherwise, `OperationStatus.SUCCESS`.
      Throws:
        `OperationFailureException` - if one of the Read Operation Failures occurs.
        `EnvironmentFailureException` - if an unexpected, internal or environment-wide failure occurs.
        `IllegalStateException` - if the database has been closed.
        `IllegalArgumentException` - if an invalid parameter is specified.
        `DatabaseException`

    - #### put

          public OperationStatus put(Transaction txn,
                            DatabaseEntry key,
                            DatabaseEntry data)
                              throws UnsupportedOperationException

      This operation is not allowed on a secondary database. `UnsupportedOperationException` will always be thrown by this method. The corresponding method on the primary database should be used instead.
      Overrides:
        `put` in class `Database`
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
        `key` - the key `DatabaseEntry` operated on.
        `data` - the data `DatabaseEntry` stored.
      Returns:
        `OperationStatus.SUCCESS` if the operation succeeds.
      Throws:
        `UnsupportedOperationException` - if this database is read-only.

    - #### putNoOverwrite

          public OperationStatus putNoOverwrite(Transaction txn,
                                       DatabaseEntry key,
                                       DatabaseEntry data)
                                         throws UnsupportedOperationException

      This operation is not allowed on a secondary database. `UnsupportedOperationException` will always be thrown by this method. The corresponding method on the primary database should be used instead.
      Overrides:
        `putNoOverwrite` in class `Database`
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
        `key` - the key `DatabaseEntry` operated on.
        `data` - the data `DatabaseEntry` stored.
      Returns:
        `OperationStatus.KEYEXIST` if the key already appears in the database, else `OperationStatus.SUCCESS`
      Throws:
        `UnsupportedOperationException` - if this database is read-only.

    - #### putNoDupData

          public OperationStatus putNoDupData(Transaction txn,
                                     DatabaseEntry key,
                                     DatabaseEntry data)
                                       throws UnsupportedOperationException

      This operation is not allowed on a secondary database. `UnsupportedOperationException` will always be thrown by this method. The corresponding method on the primary database should be used instead.
      Overrides:
        `putNoDupData` in class `Database`
      Parameters:
        `txn` - For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
        `key` - the key `DatabaseEntry` operated on.
        `data` - the data `DatabaseEntry` stored.
      Returns:
        `OperationStatus.KEYEXIST` if the key/data pair already appears in the database, else `OperationStatus.SUCCESS`
      Throws:
        `UnsupportedOperationException` - if this database is not configured for duplicates, or this database is read-only.

    - #### join

          public JoinCursor join(Cursor[] cursors,
                        JoinConfig config)
                          throws UnsupportedOperationException

      This operation is not allowed on a secondary database. `UnsupportedOperationException` will always be thrown by this method. The corresponding method on the primary database should be used instead.
      Overrides:
        `join` in class `Database`
      Parameters:
        `cursors` - an array of cursors associated with this primary database. In a replicated environment, an explicit transaction must be specified when opening each cursor, unless read-uncommitted isolation is isolation is specified via the `CursorConfig` or `LockMode` parameter.
        `config` - The join attributes. If null, default attributes are used.
      Returns:
        a specialized cursor that returns the results of the equality join operation.
      Throws:
        `UnsupportedOperationException`
      See Also:
        `JoinCursor`

Copyright (c) 2004, 2014 Oracle and/or its affiliates. All rights reserved.