| /* |
| * 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 && |
| * 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 (); |
| } |