blob: 754a11d50d58c2bbce4d1b643ebdecd215c9dbc6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.kernel;
import java.util.BitSet;
import java.util.Collection;
import java.util.List;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.ValueStrategies;
/**
* Interface to be implemented by data store mechanisms to interact with
* this runtime.
*
* @author Abe White
*/
public interface StoreManager
extends Closeable {
int VERSION_LATER = 1;
int VERSION_EARLIER = 2;
int VERSION_SAME = 3;
int VERSION_DIFFERENT = 4;
int FORCE_LOAD_NONE = 0;
int FORCE_LOAD_DFG = 1;
int FORCE_LOAD_REFRESH = 3;
int FORCE_LOAD_ALL = 2;
/**
* Set a reference to the corresponding context. This method
* will be called before the store manager is used. The store manager
* is responsible for pulling any necessary configuration data from the
* context, including the transaction mode and connection retain mode.
*/
void setContext(StoreContext ctx);
/**
* Notification that an optimistic transaction has started. This method
* does not replace the {@link #begin} method, which will still be called
* when a true data store transaction should begin.
*/
void beginOptimistic();
/**
* Notification that an optimistic transaction was rolled back before
* a data store transaction ever began.
*/
void rollbackOptimistic();
/**
* Begin a data store transaction. After this method is called,
* it is assumed that all further operations are operating in a single
* transaction that can be committed or rolled back. If optimistic
* transactions are in use, this method will only be called when the
* system requires a transactionally consistent connection due to a
* user request to flush or commit the transaction. In this case, it
* is possible that the optimistic transaction does not have the latest
* versions of all instances (i.e. another transaction has modified the
* same instances and committed since the optimistic transaction started).
* On commit, an exception must be thrown on any attempt to overwrite
* data for an instance with an older version.
*
* @since 0.2.5
*/
void begin();
/**
* Commit the current data store transaction.
*/
void commit();
/**
* Rollback the current data store transaction.
*/
void rollback();
/**
* Verify that the given instance exists in the data store; return false
* if it does not.
*/
boolean exists(OpenJPAStateManager sm, Object edata);
/**
* Verify that the given instance exists in the data store in memory; return false
* if it does not. When an object is found in memory the corresponding element of
* the BitSet is set to 1.
*/
boolean isCached(List<Object> oids, BitSet edata);
/**
* Update the version information in the given state manager to the
* version stored in the data store.
*
* @param sm the instance to check
* @param edata the current execution data, or null if not
* given to the calling method of the context
* @return true if the instance still exists in the
* datastore and is up-to-date, false otherwise
*/
boolean syncVersion(OpenJPAStateManager sm, Object edata);
/**
* Initialize the given state manager. The object id of the
* state manager will be set, and the state manager's metadata be set to
* the class of the instance to load, or possibly one of its superclasses.
* Initialization involves first calling the
* {@link OpenJPAStateManager#initialize} method with
* a new instance of the correct type constructed with the
* {@link org.apache.openjpa.enhance.PCRegistry#newInstance(Class,
* org.apache.openjpa.enhance.StateManager, boolean)} method
* (this will reset the state manager's metadata if the actual type was a
* subclass). After instance initialization, load any the fields for the
* given fetch configuration that can be efficiently retrieved. If any of
* the configured fields are not loaded in this method, they will be
* loaded with a subsequent call to {@link #load}. If this method is
* called during a data store transaction, the instance's database record
* should be locked. Version information can be loaded if desired through
* the {@link OpenJPAStateManager#setVersion} method.
*
* @param sm the instance to initialize
* @param state the lifecycle state to initialize the state manager with
* @param fetch configuration for how to load the instance
* @param edata the current execution data, or null if not
* given to the calling method of the broker
* @return true if the matching instance exists in the data
* store, false otherwise
*/
boolean initialize(OpenJPAStateManager sm, PCState state,
FetchConfiguration fetch, Object edata);
/**
* Load the given state manager.
* Note that any collection or map types loaded into the state manager
* will be proxied with the correct type; therefore the store manager
* does not have to load the same concrete collection/map types as the
* instance declares. However, array types must be consistent with the
* array type stored by the persistence capable instance. If this method
* is called during a data store transaction, the instance should be
* locked. If the given state manager does not have its version set
* already, version information can be loaded if desired through the
* {@link OpenJPAStateManager#setVersion} method.
*
* @param sm the instance to load
* @param fields set of fields to load; all field indexes in this
* set must be loaded; this set is mutable
* @param fetch the fetch configuration to use when loading
* related objects
* @param lockLevel attempt to load simple fields at this lock level;
* relations should be loaded at the read lock level
* of the fetch configuration
* @param edata the current execution data, or null if not
* given to the calling method of the broker
* @return false if the object no longer exists in the
* database, true otherwise
*/
boolean load(OpenJPAStateManager sm, BitSet fields,
FetchConfiguration fetch, int lockLevel, Object edata);
/**
* Initialize, load, or validate the existance of all of the given
* objects. This method is called from various broker methods that act
* on multiple objects, such as {@link StoreContext#retrieveAll}. It gives
* the store manager an opportunity to efficiently batch-load data for
* several objects. Each of the given state managers will be in one of
* three states, each requiring a different action:
* <ul>
* <li><code>stateManager.getO () == null</code>: An
* uninitialized state manager. Perform the same actions as in
* {@link #initialize}.
* <li><code>load != FORCE_LOAD_NONE || stateManager.getPCState ()
* == PCState.HOLLOW</code>: A hollow state manager, or one whose
* fields must be loaded because this is a refresh or retrieve action.
* Peform the same actions as in {@link #load}, choosing the fields
* to load based on the fetch configuration, or loading all fields
* if <code>load == FORCE_LOAD_ALL</code>. Any required fields left
* unloaded will cause a subsequent invocation of {@link #load} on
* the individual object in question.</li>
* <li><code>load == FORCE_LOAD_NONE &amp;&amp;
* stateManager.getPCState () != PCState.HOLLOW</code>: A non-hollow
* state manager. Perform the same actions as in {@link #exists},
* and load additional state if desired. Non-hollow objects will only
* be included outside of refresh invocations if a user calls
* <code>findAll</code> with the <code>validate</code>
* parameter set to <code>true</code>.</li>
* </ul>
* Store managers that cannot efficiently batch load can simply test
* for these conditions and delegate to the proper methods.
*
* @param sms the state manager instances to load
* @param state the lifecycle state to initialize uninitialized
* state managers with; may be null if no uninitialized
* instances are included in <code>sms</code>
* @param load one of the FORCE_LOAD_* constants describing the
* fields to force-load if this is a refresh or retrieve action
* @param fetch the current fetch configuration to use when loading
* related objects
* @param edata the current execution data, or null if not
* given to the calling method of the broker
* @return a collection of the state manager identities for
* which no data store record exists
* @see org.apache.openjpa.util.ImplHelper#loadAll
*/
Collection<Object> loadAll(Collection<OpenJPAStateManager> sms, PCState state, int load,
FetchConfiguration fetch, Object edata);
/**
* Notification that the given state manager is about to change its
* lifecycle state. The store manager is not required to do anything in
* this method, but some back ends may need to.
*
* @since 0.3.0
*/
void beforeStateChange(OpenJPAStateManager sm, PCState fromState,
PCState toState);
/**
* Flush the given state manager collection to the datastore, returning
* a collection of exceptions encountered during flushing.
* The given collection may include states that do not require data
* store action, such as persistent-clean instances or persistent-dirty
* instances that have not been modified since they were last flushed.
* For datastore updates and inserts, the dirty, non-flushed fields of
* each state should be flushed. New instances without an assigned object
* id should be given one via {@link OpenJPAStateManager#setObjectId}. New
* instances with value-strategy fields that have not been assigned yet
* should have their fields set. Datastore version information should be
* updated during flush, and the state manager's version indicator
* updated through the {@link OpenJPAStateManager#setNextVersion} method.
* The current version will roll over to this next version upon successful
* commit.
*
* @see org.apache.openjpa.util.ApplicationIds#assign()
*/
Collection<Exception> flush(Collection<OpenJPAStateManager> sms);
/**
* Assign an object id to the given new instance. Return false if the
* instance cannot be assigned an identity because a flush is required
* (for example, the identity is determined by the datastore on insert).
* For application identity instances, the assigned object id should be
* based on field state. The implementation is responsible for using the
* proper value strategy according to the instance metadata. This method
* is called the first time a user requests the oid of a new instance
* before flush.
*
* @param preFlush whether this assignment is being requested by the
* system as part of pre-flush activities, and can
* be ignored if it is more efficient to assign within {@link #flush}
* @see org.apache.openjpa.util.ImplHelper#generateFieldValue
* @see org.apache.openjpa.util.ImplHelper#generateIdentityValue
* @see org.apache.openjpa.util.ApplicationIds#assign()
* @since 0.3.3
*/
boolean assignObjectId(OpenJPAStateManager sm, boolean preFlush);
/**
* Assign a value to the given field. Return false if the value cannot
* be assigned because a flush is required (for example, the field value
* is determined by the datastore on insert). This method is called the
* first time a user requests the value of a field with a value-strategy
* on a new instance before flush.
*
* @param preFlush whether this assignment is being requested by the
* system as part of pre-flush activities, and can
* be ignored if it is more efficient to assign within {@link #flush}
* @see org.apache.openjpa.util.ImplHelper#generateFieldValue
* @since 0.4.0
*/
boolean assignField(OpenJPAStateManager sm, int field,
boolean preFlush);
/**
* Return the persistent class for the given data store identity value.
* If the given value is not a datastore identity object, return null.
*
* @since 0.3.0
*/
Class<?> getManagedType(Object oid);
/**
* Return the class used by this StoreManager for datastore identity
* values. The given metadata may be null, in which case the return
* value should the common datastore identity class for all classes, or
* null if this store manager does not use a common identity class.
*/
Class<?> getDataStoreIdType(ClassMetaData meta);
/**
* Copy the given object id value. Use the described type of the given
* metadata, which may be a subclass of the given oid's described type.
*/
Object copyDataStoreId(Object oid, ClassMetaData meta);
/**
* Create a new unique datastore identity for the given type from
* the given oid value (presumably pk, stringified oid, or oid instance).
*/
Object newDataStoreId(Object oidVal, ClassMetaData meta);
/**
* Return a connection to the data store suitable for client use. If
* this method is called during a data store transaction, thie connection
* must be transactional. If no connection is in use, this method should
* create one to return.
*/
Object getClientConnection();
/**
* Instruct the store to retain a connection for continued use. This
* will be invoked automatically based on the user's configured connection
* retain mode.
*/
void retainConnection();
/**
* Instruct the store to release a retained connection. This
* will be invoked automatically based on the user's configured connection
* retain mode.
*/
void releaseConnection();
/**
* Cancel all pending data store statements.
*
* @return true if any statements cancelled, false otherwise
* @since 0.3.1
*/
boolean cancelAll();
/**
* Return a provider for all instances of the given candidate class,
* optionally including subclasses. The given candidate may be an
* unmapped type with mapped subclasses. If the provider is iterated
* within a data store transaction, returned instances should be locked.
*/
ResultObjectProvider executeExtent(ClassMetaData meta,
boolean subclasses, FetchConfiguration fetch);
/**
* Return a query implementation suitable for this store. If the query
* is iterated within a data store transaction, returned instances should
* be locked. Return null if this store does not support native execution
* of the given language. OpenJPA can execute JPQL in memory even without
* back end support.
*
* @param language the query language
*/
StoreQuery newQuery(String language);
/**
* Return a fetch configuration suitable for this runtime. Typically
* will be or extend <code>FetchConfigurationImpl</code>.
*/
FetchConfiguration newFetchConfiguration();
/**
* Compare the two version objects.
*
* @param state the state manager for the object
* @param v1 the first version object to compare
* @param v2 the second version object to compare
* @return <ul>
* <li>{@link #VERSION_LATER} if <code>v1</code>
* is later than <code>v2</code></li>
* <li>{@link #VERSION_EARLIER} if <code>v1</code>
* is earlier than <code>v2</code></li>
* <li>{@link #VERSION_SAME} if <code>v1</code>
* is the same as <code>v2</code></li>
* <li>{@link #VERSION_DIFFERENT} if <code>v1</code>
* is different from <code>v2</code>, but the time
* difference of the versions cannot be determined</li>
* </ul>
*/
int compareVersion(OpenJPAStateManager state, Object v1, Object v2);
/**
* Return a sequence that generates datastore identity values for the
* given class. This method will only be called when the identity strategy
* for the class is one of:
* <ul>
* <li>{@link ValueStrategies#NATIVE}</li>
* <li>{@link ValueStrategies#AUTOASSIGN}</li>
* <li>{@link ValueStrategies#INCREMENT}</li>
* </ul>
* If the identity strategy cannot be represented as a sequence, return
* null.
*
* @since 0.4.0
*/
Seq getDataStoreIdSequence(ClassMetaData forClass);
/**
* Return a sequence that generates values for the given field. This
* method will only be called when the value strategy for the field
* is one of:
* <ul>
* <li>{@link ValueStrategies#NATIVE}</li>
* <li>{@link ValueStrategies#AUTOASSIGN}</li>
* <li>{@link ValueStrategies#INCREMENT}</li>
* </ul> If the value strategy cannot be represented as a sequence, return
* null.
*
* @since 0.4.0
*/
Seq getValueSequence(FieldMetaData forField);
/**
* Free any resources this store manager is using.
*
* @since 0.2.5
*/
@Override void close ();
}