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.Map;
 
 /* <!-- begin JE only --> */
 /* <!-- end JE only --> */
 /* <!-- begin JE only --> */
 /* <!-- end JE only --> */
The primary index for an entity class and its primary key.

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

PrimaryIndex implements EntityIndex to map the primary key type (PK) to the entity type (E).

The com.sleepycat.persist.model.Entity annotation may be used to define an entity class and the com.sleepycat.persist.model.PrimaryKey annotation may be used to define a primary key as shown in the following example.

 @Entity
 class Employee {

     @PrimaryKey
     long id;

     String name;

     Employee(long id, String name) {
         this.id = id;
         this.name = name;
     }

     private Employee() {} // For bindings
 }

To obtain the PrimaryIndex for a given entity class, call EntityStore.getPrimaryIndex(java.lang.Class,java.lang.Class), passing the primary key class and the entity class. For example:

 EntityStore store = new EntityStore(...);

 PrimaryIndex<Long, Employee> primaryIndex =
     store.getPrimaryIndex(Long.class, Employee.class);

Note that Long.class is passed as the primary key class, but the primary key field has the primitive type long. When a primitive primary key field is used, the corresponding primitive wrapper class is used to access the primary index. For more information on key field types, see com.sleepycat.persist.model.PrimaryKey.

The PrimaryIndex provides the primary storage and access methods for the instances of a particular entity class. Entities are inserted and updated in the PrimaryIndex by calling a method in the family of put(java.lang.Object) methods. The put(java.lang.Object) method will insert the entity if no entity with the same primary key already exists. If an entity with the same primary key does exist, it will update the entity and return the existing (old) entity. For example:

 Employee oldEntity;
 oldEntity = primaryIndex.put(new Employee(1, "Jane Smith"));    // Inserts an entity
 assert oldEntity == null;
 oldEntity = primaryIndex.put(new Employee(2, "Joan Smith"));    // Inserts an entity
 assert oldEntity == null;
 oldEntity = primaryIndex.put(new Employee(2, "Joan M. Smith")); // Updates an entity
 assert oldEntity != null;

The putNoReturn(java.lang.Object) method can be used to avoid the overhead of returning the existing entity, when the existing entity is not important to the application. The return type of putNoReturn(java.lang.Object) is void. For example:

 primaryIndex.putNoReturn(new Employee(1, "Jane Smith"));    // Inserts an entity
 primaryIndex.putNoReturn(new Employee(2, "Joan Smith"));    // Inserts an entity
 primaryIndex.putNoReturn(new Employee(2, "Joan M. Smith")); // Updates an entity

The putNoOverwrite(java.lang.Object) method can be used to ensure that an existing entity is not overwritten. putNoOverwrite(java.lang.Object) returns true if the entity was inserted, or false if an existing entity exists and no action was taken. For example:

 boolean inserted;
 inserted = primaryIndex.putNoOverwrite(new Employee(1, "Jane Smith"));    // Inserts an entity
 assert inserted;
 inserted = primaryIndex.putNoOverwrite(new Employee(2, "Joan Smith"));    // Inserts an entity
 assert inserted;
 inserted = primaryIndex.putNoOverwrite(new Employee(2, "Joan M. Smith")); // No action was taken!
 assert !inserted;

Primary key values must be unique, in other words, each instance of a given entity class must have a distinct primary key value. Rather than assigning the unique primary key values yourself, a sequence can be used to assign sequential integer values automatically, starting with the value 1 (one). A sequence is defined using the com.sleepycat.persist.model.PrimaryKey.sequence() annotation property. For example:

 @Entity
 class Employee {

     @PrimaryKey(sequence="ID")
     long id;

     String name;

     Employee(String name) {
         this.name = name;
     }

     private Employee() {} // For bindings
 }

The name of the sequence used above is "ID". Any name can be used. If the same sequence name is used in more than one entity class, the sequence will be shared by those classes, in other words, a single sequence of integers will be used for all instances of those classes. See com.sleepycat.persist.model.PrimaryKey.sequence() for more information.

Any method in the family of put(java.lang.Object) methods may be used to insert entities where the primary key is assigned from a sequence. When the put(java.lang.Object) method returns, the primary key field of the entity object will be set to the assigned key value. For example:

 Employee employee;
 employee = new Employee("Jane Smith");
 primaryIndex.putNoReturn(employee);    // Inserts an entity
 assert employee.id == 1;
 employee = new Employee("Joan Smith");
 primaryIndex.putNoReturn(employee);    // Inserts an entity
 assert employee.id == 2;

This begs the question: How do you update an existing entity, without assigning a new primary key? The answer is that the put(java.lang.Object) methods will only assign a new key from the sequence if the primary key field is zero or null (for reference types). If an entity with a non-zero and non-null key field is passed to a put(java.lang.Object) method, any existing entity with that primary key value will be updated. For example:

 Employee employee;
 employee = new Employee("Jane Smith");
 primaryIndex.putNoReturn(employee);    // Inserts an entity
 assert employee.id == 1;
 employee = new Employee("Joan Smith");
 primaryIndex.putNoReturn(employee);    // Inserts an entity
 assert employee.id == 2;
 employee.name = "Joan M. Smith";
 primaryIndex.putNoReturn(employee);    // Updates an existing entity
 assert employee.id == 2;

Since PrimaryIndex implements the EntityIndex interface, it shares the common index methods for retrieving and deleting entities, opening cursors and using transactions. See EntityIndex for more information on these topics.

Note that when using an index, keys and values are stored and retrieved by value not by reference. In other words, if an entity object is stored and then retrieved, or retrieved twice, each object will be a separate instance. For example, in the code below the assertion will always fail.

 MyKey key = ...;
 MyEntity entity1 = new MyEntity(key, ...);
 index.put(entity1);
 MyEntity entity2 = index.get(key);
 assert entity1 == entity2; // always fails!
 

Author(s):
Mark Hayes
public class PrimaryIndex<PK, E> extends BasicIndex<PK, E> {
    private Class<E> entityClass;
    private EntityBinding<E> entityBinding;
    private SortedMap<PK, E> map;
    private PersistKeyAssigner keyAssigner;

    
Creates a primary index without using an EntityStore.

This constructor is not normally needed and is provided for applications that wish to use custom bindings along with the Direct Persistence Layer. Normally, getPrimaryIndex is used instead.

Note that when this constructor is used directly, primary keys cannot be automatically assigned from a sequence. The key assignment feature requires knowledge of the primary key field, which is only available if an EntityStore is used. Of course, primary keys may be assigned from a sequence manually before calling the put methods in this class.

Parameters:
database the primary database.
keyClass the class of the primary key.
keyBinding the binding to be used for primary keys.
entityClass the class of the entities stored in this index.
entityBinding the binding to be used for entities.
Throws:
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public PrimaryIndex(Database database,
                        Class<PK> keyClass,
                        EntryBinding<PK> keyBinding,
                        Class<E> entityClass,
                        EntityBinding<E> entityBinding)
        throws DatabaseException {
        super(databasekeyClasskeyBinding,
              new EntityValueAdapter(entityClassentityBindingfalse));
        this. = entityClass;
        this. = entityBinding;
        if (entityBinding instanceof PersistEntityBinding) {
             =
                ((PersistEntityBindingentityBinding).getKeyAssigner();
        }
    }

    
Returns the underlying database for this index.

Returns:
the database.
    public Database getDatabase() {
        return ;
    }

    
Returns the primary key class for this index.

Returns:
the key class.
    public Class<PK> getKeyClass() {
        return ;
    }

    
Returns the primary key binding for this index.

Returns:
the key binding.
    public EntryBinding<PK> getKeyBinding() {
        return ;
    }

    
Returns the entity class for this index.

Returns:
the entity class.
    public Class<E> getEntityClass() {
        return ;
    }

    
Returns the entity binding for this index.

Returns:
the entity binding.
    public EntityBinding<E> getEntityBinding() {
        return ;
    }

    
Inserts an entity and returns null, or updates it if the primary key already exists and returns the existing entity.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Auto-commit is used implicitly if the store is transactional.

Parameters:
entity the entity to be inserted or updated.
Returns:
the existing entity that was updated, or null if the entity was inserted.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public E put(E entity)
        throws DatabaseException {
        return put(nullentity);
    }

    
Inserts an entity and returns null, or updates it if the primary key already exists and returns the existing entity.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Parameters:
txn the transaction used to protect this operation, null to use auto-commit, or null if the store is non-transactional.
entity the entity to be inserted or updated.
Returns:
the existing entity that was updated, or null if the entity was inserted.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public E put(Transaction txn, E entity)
        throws DatabaseException {
        DatabaseEntry keyEntry = new DatabaseEntry();
        DatabaseEntry dataEntry = new DatabaseEntry();
        assignKey(entitykeyEntry);
        boolean autoCommit = false;
        Environment env = .getEnvironment();
        if ( &&
            txn == null &&
            DbCompat.getThreadTransaction(env) == null) {
            txn = env.beginTransaction(nullgetAutoCommitTransactionConfig());
            autoCommit = true;
        }
        
        CursorConfig cursorConfig = null;
        if () {
            cursorConfig = new CursorConfig();
            DbCompat.setWriteCursor(cursorConfigtrue);
        } 
        boolean failed = true;
        Cursor cursor = .openCursor(txncursorConfig);
        LockMode lockMode =  ? . : null;
        try {
            while (true) {
                OperationStatus status =
                    cursor.getSearchKey(keyEntrydataEntrylockMode);
                if (status == .) {
                    E existing =
                        .entryToObject(keyEntrydataEntry);
                    .objectToData(entitydataEntry);
                    cursor.put(keyEntrydataEntry);
                    failed = false;
                    return existing;
                } else {
                    .objectToData(entitydataEntry);
                    status = cursor.putNoOverwrite(keyEntrydataEntry);
                    if (status != .) {
                        failed = false;
                        return null;
                    }
                }
            }
        } finally {
            cursor.close();
            if (autoCommit) {
                if (failed) {
                    txn.abort();
                } else {
                    txn.commit();
                }
            }
        }
    }

    
Inserts an entity, or updates it if the primary key already exists (does not return the existing entity). This method may be used instead of put(java.lang.Object) to save the overhead of returning the existing entity.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Auto-commit is used implicitly if the store is transactional.

Parameters:
entity the entity to be inserted or updated.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public void putNoReturn(E entity)
        throws DatabaseException {
        putNoReturn(nullentity);
    }

    
Inserts an entity, or updates it if the primary key already exists (does not return the existing entity). This method may be used instead of put(com.sleepycat.je.Transaction,java.lang.Object) to save the overhead of returning the existing entity.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Parameters:
txn the transaction used to protect this operation, null to use auto-commit, or null if the store is non-transactional.
entity the entity to be inserted or updated.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public void putNoReturn(Transaction txn, E entity)
        throws DatabaseException {
        DatabaseEntry keyEntry = new DatabaseEntry();
        DatabaseEntry dataEntry = new DatabaseEntry();
        assignKey(entitykeyEntry);
        .objectToData(entitydataEntry);
        .put(txnkeyEntrydataEntry);
    }

    
Inserts an entity and returns true, or returns false if the primary key already exists.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Auto-commit is used implicitly if the store is transactional.

Parameters:
entity the entity to be inserted.
Returns:
true if the entity was inserted, or false if an entity with the same primary key is already present.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public boolean putNoOverwrite(E entity)
        throws DatabaseException {
        return putNoOverwrite(nullentity);
    }

    
Inserts an entity and returns true, or returns false if the primary key already exists.

If a com.sleepycat.persist.model.PrimaryKey.sequence() is used and the primary key field of the given entity is null or zero, this method will assign the next value from the sequence to the primary key field of the given entity.

Parameters:
txn the transaction used to protect this operation, null to use auto-commit, or null if the store is non-transactional.
entity the entity to be inserted.
Returns:
true if the entity was inserted, or false if an entity with the same primary key is already present.
Throws:
com.sleepycat.je.OperationFailureException if one of the Write Operation Failures occurs.
com.sleepycat.je.EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
com.sleepycat.je.DatabaseException the base class for all BDB exceptions.
    public boolean putNoOverwrite(Transaction txn, E entity)
        throws DatabaseException {
        DatabaseEntry keyEntry = new DatabaseEntry();
        DatabaseEntry dataEntry = new DatabaseEntry();
        assignKey(entitykeyEntry);
        .objectToData(entitydataEntry);
        OperationStatus status = .putNoOverwrite(txnkeyEntrydataEntry);
        return (status == .);
    }

    
If we are assigning primary keys from a sequence, assign the next key and set the primary key field.
    private void assignKey(E entityDatabaseEntry keyEntry)
        throws DatabaseException {
        if ( != null) {
            if (!.assignPrimaryKey(entitykeyEntry)) {
                .objectToKey(entitykeyEntry);
            }
        } else {
            .objectToKey(entitykeyEntry);
        }
    }
    /*
     * Of the EntityIndex methods only get()/map()/sortedMap() are implemented
     * here.  All other methods are implemented by BasicIndex.
     */
    public E get(PK key)
        throws DatabaseException {
        return get(nullkeynull);
    }
    public E get(Transaction txn, PK keyLockMode lockMode)
        throws DatabaseException {
        DatabaseEntry keyEntry = new DatabaseEntry();
        DatabaseEntry dataEntry = new DatabaseEntry();
        .objectToEntry(keykeyEntry);
        OperationStatus status = .get(txnkeyEntrydataEntrylockMode);
        if (status == .) {
            if ( instanceof PersistEntityBinding) {
                return (E)((PersistEntityBinding).
                           entryToObjectWithPriKey(keydataEntry);
            } else {
                return .entryToObject(keyEntrydataEntry);
            }
        } else {
            return null;
        }
    }
    public Map<PK, E> map() {
        return sortedMap();
    }
    public synchronized SortedMap<PK, E> sortedMap() {
        if ( == null) {
             = new StoredSortedMap(true);
        }
        return ;
    }

    

Hidden:
For internal use only. Used for obtaining the auto-commit txn config from the store, which overrides this method to return it.
    /* <!-- begin JE only --> */
    protected
    /* <!-- end JE only --> */
        return null;
    }
    boolean isUpdateAllowed() {
        return true;
    }
New to GrepCode? Check out our FAQ X