/**
* Copyright 2009-2013 Oy Vaadin Ltd
*
* Licensed 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 com.vaadin.addon.jpacontainer;
import java.io.Serializable;
/**
* An extended version of {@link MutableEntityProvider} that can execute several
* update operations (that is, adding new entities, and updating and removing
* existing entities) inside a single transaction. This feature is used by
* {@link JPAContainer} when write-through/auto-commit is turned off.
* <p>
* If the entites handled by this provider contain complex associations, special
* care should be taken to enforce data integrity. The following example
* scenarios might give unexpected results if not dealt with properly:
* <p>
* <b>Example 1</b>
* <ol>
* <li>Add Entity1</li>
* <li>Add Entity2</li>
* <li>Update Entity1 to reference Entity2</li>
* <li>Run batch</li>
* </ol>
* Depending on the entity manager implementation and cascading settings, this
* might cause an exception due to a nonexistent reference to Entity2 at step 1,
* or a duplicate of Entity2 at step 2.
* <p>
* <b>Example 2</b>
* <ol>
* <li>Add Entity1</li>
* <li>Add Entity2</li>
* <li>Update Entity1 to reference Entity2</li>
* <li>Remove Entity2</li>
* <li>Run batch</li>
* </ol>
* First of all, Entity2 should not be added at all as it is added and removed
* inside the same transaction. However, there is still a reference to Entity2
* from Entity1. If cascading is turned on, this might result in both Entity1
* and Entity2 being added nonetheless.
*
* @see JPAContainer#setWriteThrough(boolean)
* @see JPAContainer#isWriteThrough()
* @author Petter Holmström (Vaadin Ltd)
* @since 1.0
*/
public interface BatchableEntityProvider<T> extends MutableEntityProvider<T> {
/**
* Callback interface used by the
* {@link BatchableEntityProvider#batchUpdate(com.vaadin.addon.jpacontainer.BatchableEntityProvider.BatchUpdateCallback) }
* method.
*
* @author Petter Holmström (Vaadin Ltd)
* @since 1.0
*/
public static interface BatchUpdateCallback<T> extends Serializable {
/**
* Runs the updates using a special batch enabled mutable entity
* provider.
*
* @param batchEnabledEntityProvider
* a {@link MutableEntityProvider} that knows how to handle
* multiple updates and executes them within a single
* transaction.
*/
public void batchUpdate(
MutableEntityProvider<T> batchEnabledEntityProvider);
}
/**
* Executes a batch update using the specified callback parameter. The batch
* update should be run inside a single transaction. The implementation may
* either handle the transaction itself, or rely on external transaction
* handling provided by a container such as Spring or EJB. If the batch
* update fails, the entire transaction should be rolled back and an
* exception thrown. Otherwise, it should be committed.
* <p>
* Clients should instantiate {@link BatchUpdateCallback}, implement the
* {@link BatchUpdateCallback#batchUpdate(MutableEntityProvider) } method and
* execute the updates as if they were using an ordinary
* {@link MutableEntityProvider}. The following example saves a list of
* transient entities: <code>
* <pre>
* provider.batchUpdate(new BatchUpdateCallback<MyEntity>() {
* public void batchUpdate(MutableEntityProvider<MyEntity> batchEnabledEntityProvider) {
* for (Entity e : myListOfEntitiesToAdd) {
* batchEnabledEntityProvider.addEntity(e);
* }
* }
* });
* </pre></code>
*
* @param callback
* the callback that will be used to run the batch update.
* @throws UnsupportedOperationException
* if this entity provider does not support batch updates.
*/
public void batchUpdate(BatchUpdateCallback<T> callback)
throws UnsupportedOperationException;
}