Apply spring-javaformat style for consistency with other projects
Resolves #4118
This commit is contained in:
@@ -25,12 +25,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Object representing a context for an {@link ItemStream}. It is a thin wrapper
|
||||
* for a map that allows optionally for type safety on reads. It also allows for
|
||||
* dirty checking by setting a 'dirty' flag whenever any put is called.
|
||||
* Object representing a context for an {@link ItemStream}. It is a thin wrapper for a map
|
||||
* that allows optionally for type safety on reads. It also allows for dirty checking by
|
||||
* setting a 'dirty' flag whenever any put is called.
|
||||
*
|
||||
* Note that putting <code>null</code> value is equivalent to removing the entry
|
||||
* for the given key.
|
||||
* Note that putting <code>null</code> value is equivalent to removing the entry for the
|
||||
* given key.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Douglas Kaminsky
|
||||
@@ -44,8 +44,8 @@ public class ExecutionContext implements Serializable {
|
||||
private final Map<String, Object> map;
|
||||
|
||||
/**
|
||||
* Default constructor. Initializes a new execution context with an empty
|
||||
* internal map.
|
||||
* Default constructor. Initializes a new execution context with an empty internal
|
||||
* map.
|
||||
*/
|
||||
public ExecutionContext() {
|
||||
this.map = new ConcurrentHashMap<>();
|
||||
@@ -53,7 +53,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Initializes a new execution context with the contents of another map.
|
||||
*
|
||||
* @param map Initial contents of context.
|
||||
*/
|
||||
public ExecutionContext(Map<String, Object> map) {
|
||||
@@ -63,8 +62,8 @@ public class ExecutionContext implements Serializable {
|
||||
/**
|
||||
* Initializes a new {@link ExecutionContext} with the contents of another
|
||||
* {@code ExecutionContext}.
|
||||
*
|
||||
* @param executionContext containing the entries to be copied to this current context.
|
||||
* @param executionContext containing the entries to be copied to this current
|
||||
* context.
|
||||
*/
|
||||
public ExecutionContext(ExecutionContext executionContext) {
|
||||
this();
|
||||
@@ -77,9 +76,8 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a String value to the context. Putting <code>null</code>
|
||||
* value for a given key removes the key.
|
||||
*
|
||||
* Adds a String value to the context. Putting <code>null</code> value for a given key
|
||||
* removes the key.
|
||||
* @param key Key to add to context
|
||||
* @param value Value to associate with key
|
||||
*/
|
||||
@@ -91,7 +89,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Adds a Long value to the context.
|
||||
*
|
||||
* @param key Key to add to context
|
||||
* @param value Value to associate with key
|
||||
*/
|
||||
@@ -102,7 +99,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Adds an Integer value to the context.
|
||||
*
|
||||
* @param key Key to add to context
|
||||
* @param value Value to associate with key
|
||||
*/
|
||||
@@ -112,7 +108,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Add a Double value to the context.
|
||||
*
|
||||
* @param key Key to add to context
|
||||
* @param value Value to associate with key
|
||||
*/
|
||||
@@ -122,28 +117,26 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an Object value to the context. Putting <code>null</code>
|
||||
* value for a given key removes the key.
|
||||
*
|
||||
* Add an Object value to the context. Putting <code>null</code> value for a given key
|
||||
* removes the key.
|
||||
* @param key Key to add to context
|
||||
* @param value Value to associate with key
|
||||
*/
|
||||
public void put(String key, @Nullable Object value) {
|
||||
if (value != null) {
|
||||
Object result = this.map.put(key, value);
|
||||
this.dirty = result==null || result!=null && !result.equals(value);
|
||||
this.dirty = result == null || result != null && !result.equals(value);
|
||||
}
|
||||
else {
|
||||
Object result = this.map.remove(key);
|
||||
this.dirty = result!=null;
|
||||
this.dirty = result != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if context has been changed with a "put" operation since the
|
||||
* dirty flag was last cleared. Note that the last time the flag was cleared
|
||||
* might correspond to creation of the context.
|
||||
*
|
||||
* Indicates if context has been changed with a "put" operation since the dirty flag
|
||||
* was last cleared. Note that the last time the flag was cleared might correspond to
|
||||
* creation of the context.
|
||||
* @return True if "put" operation has occurred since flag was last cleared
|
||||
*/
|
||||
public boolean isDirty() {
|
||||
@@ -152,7 +145,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the String represented by the provided key.
|
||||
*
|
||||
* @param key The key to get a value for
|
||||
* @return The <code>String</code> value
|
||||
*/
|
||||
@@ -162,13 +154,12 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the String represented by the provided key with
|
||||
* default value to return if key is not represented.
|
||||
*
|
||||
* Typesafe Getter for the String represented by the provided key with default value
|
||||
* to return if key is not represented.
|
||||
* @param key The key to get a value for
|
||||
* @param defaultString Default to return if key is not represented
|
||||
* @return The <code>String</code> value if key is represented, specified
|
||||
* default otherwise
|
||||
* @return The <code>String</code> value if key is represented, specified default
|
||||
* otherwise
|
||||
*/
|
||||
public String getString(String key, String defaultString) {
|
||||
if (!containsKey(key)) {
|
||||
@@ -180,7 +171,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Long represented by the provided key.
|
||||
*
|
||||
* @param key The key to get a value for
|
||||
* @return The <code>Long</code> value
|
||||
*/
|
||||
@@ -190,13 +180,12 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Long represented by the provided key with default
|
||||
* value to return if key is not represented.
|
||||
*
|
||||
* Typesafe Getter for the Long represented by the provided key with default value to
|
||||
* return if key is not represented.
|
||||
* @param key The key to get a value for
|
||||
* @param defaultLong Default to return if key is not represented
|
||||
* @return The <code>long</code> value if key is represented, specified
|
||||
* default otherwise
|
||||
* @return The <code>long</code> value if key is represented, specified default
|
||||
* otherwise
|
||||
*/
|
||||
public long getLong(String key, long defaultLong) {
|
||||
if (!containsKey(key)) {
|
||||
@@ -208,7 +197,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Integer represented by the provided key.
|
||||
*
|
||||
* @param key The key to get a value for
|
||||
* @return The <code>Integer</code> value
|
||||
*/
|
||||
@@ -218,13 +206,12 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Integer represented by the provided key with
|
||||
* default value to return if key is not represented.
|
||||
*
|
||||
* Typesafe Getter for the Integer represented by the provided key with default value
|
||||
* to return if key is not represented.
|
||||
* @param key The key to get a value for
|
||||
* @param defaultInt Default to return if key is not represented
|
||||
* @return The <code>int</code> value if key is represented, specified
|
||||
* default otherwise
|
||||
* @return The <code>int</code> value if key is represented, specified default
|
||||
* otherwise
|
||||
*/
|
||||
public int getInt(String key, int defaultInt) {
|
||||
if (!containsKey(key)) {
|
||||
@@ -236,7 +223,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Double represented by the provided key.
|
||||
*
|
||||
* @param key The key to get a value for
|
||||
* @return The <code>Double</code> value
|
||||
*/
|
||||
@@ -245,13 +231,12 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Typesafe Getter for the Double represented by the provided key with
|
||||
* default value to return if key is not represented.
|
||||
*
|
||||
* Typesafe Getter for the Double represented by the provided key with default value
|
||||
* to return if key is not represented.
|
||||
* @param key The key to get a value for
|
||||
* @param defaultDouble Default to return if key is not represented
|
||||
* @return The <code>double</code> value if key is represented, specified
|
||||
* default otherwise
|
||||
* @return The <code>double</code> value if key is represented, specified default
|
||||
* otherwise
|
||||
*/
|
||||
public double getDouble(String key, double defaultDouble) {
|
||||
if (!containsKey(key)) {
|
||||
@@ -263,10 +248,9 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Getter for the value represented by the provided key.
|
||||
*
|
||||
* @param key The key to get a value for
|
||||
* @return The value represented by the given key or {@code null} if the key
|
||||
* is not present
|
||||
* @return The value represented by the given key or {@code null} if the key is not
|
||||
* present
|
||||
*/
|
||||
@Nullable
|
||||
public Object get(String key) {
|
||||
@@ -274,9 +258,8 @@ public class ExecutionContext implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that attempts to take a value represented by a given key
|
||||
* and validate it as a member of the specified type.
|
||||
*
|
||||
* Utility method that attempts to take a value represented by a given key and
|
||||
* validate it as a member of the specified type.
|
||||
* @param key The key to validate a value for
|
||||
* @param type Class against which value should be validated
|
||||
* @return Value typed to the specified <code>Class</code>
|
||||
@@ -295,7 +278,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Indicates whether or not the context is empty.
|
||||
*
|
||||
* @return True if the context has no entries, false otherwise.
|
||||
* @see java.util.Map#isEmpty()
|
||||
*/
|
||||
@@ -312,7 +294,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Returns the entry set containing the contents of this context.
|
||||
*
|
||||
* @return A set representing the contents of the context
|
||||
* @see java.util.Map#entrySet()
|
||||
*/
|
||||
@@ -322,7 +303,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Indicates whether or not a key is represented in this context.
|
||||
*
|
||||
* @param key Key to check existence for
|
||||
* @return True if key is represented in context, false otherwise
|
||||
* @see java.util.Map#containsKey(Object)
|
||||
@@ -333,7 +313,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Removes the mapping for a key from this context if it is present.
|
||||
*
|
||||
* @param key {@link String} that identifies the entry to be removed from the context.
|
||||
* @return the value that was removed from the context.
|
||||
*
|
||||
@@ -346,7 +325,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Indicates whether or not a value is represented in this context.
|
||||
*
|
||||
* @param value Value to check existence for
|
||||
* @return True if value is represented in context, false otherwise
|
||||
* @see java.util.Map#containsValue(Object)
|
||||
@@ -394,7 +372,6 @@ public class ExecutionContext implements Serializable {
|
||||
|
||||
/**
|
||||
* Returns number of entries in the context
|
||||
*
|
||||
* @return Number of entries in the context
|
||||
* @see java.util.Map#size()
|
||||
*/
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* Copyright 20013 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||
|
||||
/**
|
||||
* Marker interface indicating that an item should have the item count set on it. Typically used within
|
||||
* an {@link AbstractItemCountingItemStreamItemReader}.
|
||||
*
|
||||
* @author Jimmy Praet
|
||||
*/
|
||||
public interface ItemCountAware {
|
||||
|
||||
/**
|
||||
* Setter for the injection of the current item count.
|
||||
*
|
||||
* @param count the number of items that have been processed in this execution.
|
||||
*/
|
||||
void setItemCount(int count);
|
||||
}
|
||||
/*
|
||||
* Copyright 20013 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||
|
||||
/**
|
||||
* Marker interface indicating that an item should have the item count set on it.
|
||||
* Typically used within an {@link AbstractItemCountingItemStreamItemReader}.
|
||||
*
|
||||
* @author Jimmy Praet
|
||||
*/
|
||||
public interface ItemCountAware {
|
||||
|
||||
/**
|
||||
* Setter for the injection of the current item count.
|
||||
* @param count the number of items that have been processed in this execution.
|
||||
*/
|
||||
void setItemCount(int count);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,37 +20,38 @@ import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for item transformation. Given an item as input, this interface provides
|
||||
* an extension point which allows for the application of business logic in an item
|
||||
* oriented processing scenario. It should be noted that while it's possible to return
|
||||
* a different type than the one provided, it's not strictly necessary. Furthermore,
|
||||
* returning {@code null} indicates that the item should not be continued to be processed.
|
||||
*
|
||||
* Interface for item transformation. Given an item as input, this interface provides an
|
||||
* extension point which allows for the application of business logic in an item oriented
|
||||
* processing scenario. It should be noted that while it's possible to return a different
|
||||
* type than the one provided, it's not strictly necessary. Furthermore, returning
|
||||
* {@code null} indicates that the item should not be continued to be processed.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @param <I> type of input item
|
||||
* @param <O> type of output item
|
||||
*/
|
||||
public interface ItemProcessor<I, O> {
|
||||
|
||||
/**
|
||||
* Process the provided item, returning a potentially modified or new item for continued
|
||||
* processing. If the returned result is {@code null}, it is assumed that processing of the item
|
||||
* should not continue.
|
||||
*
|
||||
* A {@code null} item will never reach this method because the only possible sources are:
|
||||
* Process the provided item, returning a potentially modified or new item for
|
||||
* continued processing. If the returned result is {@code null}, it is assumed that
|
||||
* processing of the item should not continue.
|
||||
*
|
||||
* A {@code null} item will never reach this method because the only possible sources
|
||||
* are:
|
||||
* <ul>
|
||||
* <li>an {@link ItemReader} (which indicates no more items)</li>
|
||||
* <li>a previous {@link ItemProcessor} in a composite processor (which indicates a filtered item)</li>
|
||||
* <li>an {@link ItemReader} (which indicates no more items)</li>
|
||||
* <li>a previous {@link ItemProcessor} in a composite processor (which indicates a
|
||||
* filtered item)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param item to be processed, never {@code null}.
|
||||
* @return potentially modified or new item for continued processing, {@code null} if processing of the
|
||||
* provided item should not continue.
|
||||
* @return potentially modified or new item for continued processing, {@code null} if
|
||||
* processing of the provided item should not continue.
|
||||
* @throws Exception thrown if exception occurs during processing.
|
||||
*/
|
||||
@Nullable
|
||||
O process(@NonNull I item) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -20,17 +20,17 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface for providing the data. <br>
|
||||
*
|
||||
* Implementations are expected to be stateful and will be called multiple times
|
||||
* for each batch, with each call to {@link #read()} returning a different value
|
||||
* and finally returning <code>null</code> when all input data is exhausted.<br>
|
||||
*
|
||||
* Implementations need <b>not</b> be thread-safe and clients of a {@link ItemReader}
|
||||
* need to be aware that this is the case.<br>
|
||||
*
|
||||
* A richer interface (e.g. with a look ahead or peek) is not feasible because
|
||||
* we need to support transactions in an asynchronous batch.
|
||||
*
|
||||
*
|
||||
* Implementations are expected to be stateful and will be called multiple times for each
|
||||
* batch, with each call to {@link #read()} returning a different value and finally
|
||||
* returning <code>null</code> when all input data is exhausted.<br>
|
||||
*
|
||||
* Implementations need <b>not</b> be thread-safe and clients of a {@link ItemReader} need
|
||||
* to be aware that this is the case.<br>
|
||||
*
|
||||
* A richer interface (e.g. with a look ahead or peek) is not feasible because we need to
|
||||
* support transactions in an asynchronous batch.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
@@ -41,22 +41,19 @@ public interface ItemReader<T> {
|
||||
|
||||
/**
|
||||
* Reads a piece of input data and advance to the next one. Implementations
|
||||
* <strong>must</strong> return <code>null</code> at the end of the input
|
||||
* data set. In a transactional setting, caller might get the same item
|
||||
* twice from successive calls (or otherwise), if the first call was in a
|
||||
* transaction that rolled back.
|
||||
*
|
||||
* @throws ParseException if there is a problem parsing the current record
|
||||
* (but the next one may still be valid)
|
||||
* @throws NonTransientResourceException if there is a fatal exception in
|
||||
* the underlying resource. After throwing this exception implementations
|
||||
* should endeavour to return null from subsequent calls to read.
|
||||
* @throws UnexpectedInputException if there is an uncategorised problem
|
||||
* with the input data. Assume potentially transient, so subsequent calls to
|
||||
* read might succeed.
|
||||
* <strong>must</strong> return <code>null</code> at the end of the input data set. In
|
||||
* a transactional setting, caller might get the same item twice from successive calls
|
||||
* (or otherwise), if the first call was in a transaction that rolled back.
|
||||
* @throws ParseException if there is a problem parsing the current record (but the
|
||||
* next one may still be valid)
|
||||
* @throws NonTransientResourceException if there is a fatal exception in the
|
||||
* underlying resource. After throwing this exception implementations should endeavour
|
||||
* to return null from subsequent calls to read.
|
||||
* @throws UnexpectedInputException if there is an uncategorised problem with the
|
||||
* input data. Assume potentially transient, so subsequent calls to read might
|
||||
* succeed.
|
||||
* @throws Exception if an there is a non-specific error.
|
||||
* @return T the item to be processed or {@code null} if the data source is
|
||||
* exhausted
|
||||
* @return T the item to be processed or {@code null} if the data source is exhausted
|
||||
*/
|
||||
@Nullable
|
||||
T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException;
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* A base exception class that all exceptions thrown from an {@link ItemReader} extend.
|
||||
*
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -26,7 +26,6 @@ public abstract class ItemReaderException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ItemReaderException} based on a message and another exception.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
* @param cause the other exception
|
||||
*/
|
||||
@@ -36,7 +35,6 @@ public abstract class ItemReaderException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ItemReaderException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public ItemReaderException(String message) {
|
||||
|
||||
@@ -18,38 +18,40 @@ package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Marker interface defining a contract for periodically storing state and restoring from that state should an error
|
||||
* occur.
|
||||
* Marker interface defining a contract for periodically storing state and restoring from
|
||||
* that state should an error occur.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface ItemStream {
|
||||
|
||||
/**
|
||||
* Open the stream for the provided {@link ExecutionContext}.
|
||||
*
|
||||
* @param executionContext current step's {@link org.springframework.batch.item.ExecutionContext}. Will be the
|
||||
* executionContext from the last run of the step on a restart.
|
||||
* @param executionContext current step's
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Will be the
|
||||
* executionContext from the last run of the step on a restart.
|
||||
* @throws IllegalArgumentException if context is null
|
||||
*/
|
||||
void open(ExecutionContext executionContext) throws ItemStreamException;
|
||||
|
||||
/**
|
||||
* Indicates that the execution context provided during open is about to be saved. If any state is remaining, but
|
||||
* has not been put in the context, it should be added here.
|
||||
*
|
||||
* Indicates that the execution context provided during open is about to be saved. If
|
||||
* any state is remaining, but has not been put in the context, it should be added
|
||||
* here.
|
||||
* @param executionContext to be updated
|
||||
* @throws IllegalArgumentException if executionContext is null.
|
||||
*/
|
||||
void update(ExecutionContext executionContext) throws ItemStreamException;
|
||||
|
||||
/**
|
||||
* If any resources are needed for the stream to operate they need to be destroyed here. Once this method has been
|
||||
* called all other methods (except open) may throw an exception.
|
||||
* If any resources are needed for the stream to operate they need to be destroyed
|
||||
* here. Once this method has been called all other methods (except open) may throw an
|
||||
* exception.
|
||||
*/
|
||||
void close() throws ItemStreamException;
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Exception representing any errors encountered while processing a stream.
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
*/
|
||||
@@ -33,10 +33,9 @@ public class ItemStreamException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructs a new instance with a message and nested exception.
|
||||
*
|
||||
* @param msg the exception message.
|
||||
* @param nested the cause of the exception.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public ItemStreamException(String msg, Throwable nested) {
|
||||
super(msg, nested);
|
||||
@@ -44,10 +43,10 @@ public class ItemStreamException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructs a new instance with a nested exception and empty message.
|
||||
*
|
||||
* @param nested the cause of the exception.
|
||||
*/
|
||||
public ItemStreamException(Throwable nested) {
|
||||
super(nested);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Convenience interface that combines {@link ItemStream} and {@link ItemReader}
|
||||
* .
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemStreamReader<T> extends ItemStream, ItemReader<T> {
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Convenience interface that combines {@link ItemStream} and {@link ItemReader} .
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemStreamReader<T> extends ItemStream, ItemReader<T> {
|
||||
|
||||
}
|
||||
|
||||
@@ -51,12 +51,11 @@ public abstract class ItemStreamSupport implements ItemStream {
|
||||
@Override
|
||||
public void update(ExecutionContext executionContext) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The name of the component which will be used as a stem for keys in the
|
||||
* {@link ExecutionContext}. Subclasses should provide a default value, e.g.
|
||||
* the short form of the class name.
|
||||
*
|
||||
* {@link ExecutionContext}. Subclasses should provide a default value, e.g. the short
|
||||
* form of the class name.
|
||||
* @param name the name for the component
|
||||
*/
|
||||
public void setName(String name) {
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Convenience interface that combines {@link ItemStream} and {@link ItemWriter}
|
||||
* .
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemStreamWriter<T> extends ItemStream, ItemWriter<T> {
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Convenience interface that combines {@link ItemStream} and {@link ItemWriter} .
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemStreamWriter<T> extends ItemStream, ItemWriter<T> {
|
||||
|
||||
}
|
||||
|
||||
@@ -20,31 +20,30 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Basic interface for generic output operations. Class implementing this
|
||||
* interface will be responsible for serializing objects as necessary.
|
||||
* Generally, it is responsibility of implementing class to decide which
|
||||
* technology to use for mapping and how it should be configured.
|
||||
* Basic interface for generic output operations. Class implementing this interface will
|
||||
* be responsible for serializing objects as necessary. Generally, it is responsibility of
|
||||
* implementing class to decide which technology to use for mapping and how it should be
|
||||
* configured.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The write method is responsible for making sure that any internal buffers are
|
||||
* flushed. If a transaction is active it will also usually be necessary to
|
||||
* discard the output on a subsequent rollback. The resource to which the writer
|
||||
* is sending data should normally be able to handle this itself.
|
||||
* The write method is responsible for making sure that any internal buffers are flushed.
|
||||
* If a transaction is active it will also usually be necessary to discard the output on a
|
||||
* subsequent rollback. The resource to which the writer is sending data should normally
|
||||
* be able to handle this itself.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
*/
|
||||
public interface ItemWriter<T> {
|
||||
|
||||
/**
|
||||
* Process the supplied data element. Will not be called with any null items
|
||||
* in normal operation.
|
||||
*
|
||||
* Process the supplied data element. Will not be called with any null items in normal
|
||||
* operation.
|
||||
* @param items items to be written
|
||||
* @throws Exception if there are errors. The framework will catch the
|
||||
* exception and convert or rethrow it as appropriate.
|
||||
* @throws Exception if there are errors. The framework will catch the exception and
|
||||
* convert or rethrow it as appropriate.
|
||||
*/
|
||||
void write(List<? extends T> items) throws Exception;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* A base exception class that all exceptions thrown from an {@link ItemWriter} extend.
|
||||
*
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -26,7 +26,6 @@ public abstract class ItemWriterException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ItemWriterException} based on a message and another exception.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
* @param cause the other exception
|
||||
*/
|
||||
@@ -36,7 +35,6 @@ public abstract class ItemWriterException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ItemWriterException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public ItemWriterException(String message) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://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.
|
||||
@@ -19,9 +19,9 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A base class to implement any {@link ItemWriter} that writes to a key value store
|
||||
* using a {@link Converter} to derive a key from an item
|
||||
*
|
||||
* A base class to implement any {@link ItemWriter} that writes to a key value store using
|
||||
* a {@link Converter} to derive a key from an item
|
||||
*
|
||||
* @author David Turanski
|
||||
* @since 2.2
|
||||
*
|
||||
@@ -29,9 +29,12 @@ import org.springframework.util.Assert;
|
||||
public abstract class KeyValueItemWriter<K, V> implements ItemWriter<V>, InitializingBean {
|
||||
|
||||
protected Converter<V, K> itemKeyMapper;
|
||||
|
||||
protected boolean delete;
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#write(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
@@ -48,10 +51,10 @@ public abstract class KeyValueItemWriter<K, V> implements ItemWriter<V>, Initial
|
||||
|
||||
/**
|
||||
* Flush items to the key/value store.
|
||||
*
|
||||
* @throws Exception if unable to flush items
|
||||
*/
|
||||
protected void flush() throws Exception {}
|
||||
protected void flush() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses implement this method to write each item to key value store
|
||||
@@ -67,7 +70,6 @@ public abstract class KeyValueItemWriter<K, V> implements ItemWriter<V>, Initial
|
||||
|
||||
/**
|
||||
* Set the {@link Converter} to use to derive the key from the item
|
||||
*
|
||||
* @param itemKeyMapper the {@link Converter} used to derive a key from an item.
|
||||
*/
|
||||
public void setItemKeyMapper(Converter<V, K> itemKeyMapper) {
|
||||
@@ -76,15 +78,16 @@ public abstract class KeyValueItemWriter<K, V> implements ItemWriter<V>, Initial
|
||||
|
||||
/**
|
||||
* Sets the delete flag to have the item writer perform deletes
|
||||
*
|
||||
* @param delete if true {@link ItemWriter} will perform deletes,
|
||||
* if false not to perform deletes.
|
||||
* @param delete if true {@link ItemWriter} will perform deletes, if false not to
|
||||
* perform deletes.
|
||||
*/
|
||||
public void setDelete(boolean delete) {
|
||||
this.delete = delete;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
@@ -92,4 +95,5 @@ public abstract class KeyValueItemWriter<K, V> implements ItemWriter<V>, Initial
|
||||
Assert.notNull(itemKeyMapper, "itemKeyMapper requires a Converter type.");
|
||||
init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,17 @@
|
||||
package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Exception indicating that an error has been encountered doing I/O from a
|
||||
* reader, and the exception should be considered fatal.
|
||||
*
|
||||
* Exception indicating that an error has been encountered doing I/O from a reader, and
|
||||
* the exception should be considered fatal.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NonTransientResourceException extends ItemReaderException {
|
||||
|
||||
/**
|
||||
* Create a new {@link NonTransientResourceException} based on a message and
|
||||
* another exception.
|
||||
*
|
||||
* Create a new {@link NonTransientResourceException} based on a message and another
|
||||
* exception.
|
||||
* @param message the message for this exception
|
||||
* @param cause the other exception
|
||||
*/
|
||||
@@ -37,7 +36,6 @@ public class NonTransientResourceException extends ItemReaderException {
|
||||
|
||||
/**
|
||||
* Create a new {@link NonTransientResourceException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public NonTransientResourceException(String message) {
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Exception indicating that an error has been encountered parsing IO, typically from a file.
|
||||
*
|
||||
* Exception indicating that an error has been encountered parsing IO, typically from a
|
||||
* file.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@@ -26,7 +27,6 @@ public class ParseException extends ItemReaderException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ParseException} based on a message and another exception.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
* @param cause the other exception
|
||||
*/
|
||||
@@ -36,7 +36,6 @@ public class ParseException extends ItemReaderException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ParseException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public ParseException(String message) {
|
||||
|
||||
@@ -19,31 +19,29 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A specialisation of {@link ItemReader} that allows the user to look ahead
|
||||
* into the stream of items. This is useful, for instance, when reading flat
|
||||
* file data that contains record separator lines which are actually part of the
|
||||
* next record.
|
||||
* A specialisation of {@link ItemReader} that allows the user to look ahead into the
|
||||
* stream of items. This is useful, for instance, when reading flat file data that
|
||||
* contains record separator lines which are actually part of the next record.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The detailed contract for {@link #peek()} has to be defined by the
|
||||
* implementation because there is no general way to define it in a concurrent
|
||||
* environment. The definition of "the next read()" operation is tenuous if
|
||||
* multiple clients are reading concurrently, and the ability to peek implies
|
||||
* that some state is likely to be stored, so implementations of
|
||||
* {@link PeekableItemReader} may well be restricted to single threaded use.
|
||||
* The detailed contract for {@link #peek()} has to be defined by the implementation
|
||||
* because there is no general way to define it in a concurrent environment. The
|
||||
* definition of "the next read()" operation is tenuous if multiple clients are reading
|
||||
* concurrently, and the ability to peek implies that some state is likely to be stored,
|
||||
* so implementations of {@link PeekableItemReader} may well be restricted to single
|
||||
* threaded use.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface PeekableItemReader<T> extends ItemReader<T> {
|
||||
|
||||
/**
|
||||
* Get the next item that would be returned by {@link #read()}, without
|
||||
* affecting the result of {@link #read()}.
|
||||
*
|
||||
* Get the next item that would be returned by {@link #read()}, without affecting the
|
||||
* result of {@link #read()}.
|
||||
* @return the next item or {@code null} if the data source is exhausted
|
||||
* @throws Exception if there is a problem
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Exception indicating that an {@link ItemReader} needed to be opened before read.
|
||||
*
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -25,7 +25,6 @@ public class ReaderNotOpenException extends ItemReaderException {
|
||||
|
||||
/**
|
||||
* Create a new {@link ReaderNotOpenException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public ReaderNotOpenException(String message) {
|
||||
@@ -33,12 +32,13 @@ public class ReaderNotOpenException extends ItemReaderException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ReaderNotOpenException} based on a message and another exception.
|
||||
*
|
||||
* Create a new {@link ReaderNotOpenException} based on a message and another
|
||||
* exception.
|
||||
* @param msg the message for this exception
|
||||
* @param nested the other exception
|
||||
*/
|
||||
public ReaderNotOpenException(String msg, Throwable nested) {
|
||||
super(msg, nested);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,13 +19,15 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.batch.item.file.MultiResourceItemReader;
|
||||
|
||||
/**
|
||||
* Marker interface indicating that an item should have the Spring {@link Resource} in which it was read from, set on it.
|
||||
* The canonical example is within {@link MultiResourceItemReader}, which will set the current resource on any items
|
||||
* that implement this interface.
|
||||
* Marker interface indicating that an item should have the Spring {@link Resource} in
|
||||
* which it was read from, set on it. The canonical example is within
|
||||
* {@link MultiResourceItemReader}, which will set the current resource on any items that
|
||||
* implement this interface.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*/
|
||||
public interface ResourceAware {
|
||||
|
||||
void setResource(Resource resource);
|
||||
void setResource(Resource resource);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://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.
|
||||
@@ -19,17 +19,23 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Converter} that uses SpEL to map a Value to a key
|
||||
*
|
||||
* @author David Turanski
|
||||
* @since 2.2
|
||||
*/
|
||||
public class SpELItemKeyMapper<K,V> implements Converter<V,K> {
|
||||
public class SpELItemKeyMapper<K, V> implements Converter<V, K> {
|
||||
|
||||
private final ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
private final Expression parsedExpression;
|
||||
|
||||
|
||||
public SpELItemKeyMapper(String keyExpression) {
|
||||
parsedExpression = parser.parseExpression(keyExpression);
|
||||
parsedExpression = parser.parseExpression(keyExpression);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemKeyMapper#mapKey(java.lang.Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -37,4 +43,5 @@ public class SpELItemKeyMapper<K,V> implements Converter<V,K> {
|
||||
public K convert(V item) {
|
||||
return (K) parsedExpression.getValue(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Used to signal an unexpected end of an input or message stream. This is an abnormal condition, not just the end of
|
||||
* the data - e.g. if a resource becomes unavailable, or a stream becomes unreadable.
|
||||
*
|
||||
* Used to signal an unexpected end of an input or message stream. This is an abnormal
|
||||
* condition, not just the end of the data - e.g. if a resource becomes unavailable, or a
|
||||
* stream becomes unreadable.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UnexpectedInputException extends ItemReaderException {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link UnexpectedInputException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public UnexpectedInputException(String message) {
|
||||
@@ -36,12 +36,13 @@ public class UnexpectedInputException extends ItemReaderException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link UnexpectedInputException} based on a message and another exception.
|
||||
*
|
||||
* Create a new {@link UnexpectedInputException} based on a message and another
|
||||
* exception.
|
||||
* @param msg the message for this exception
|
||||
* @param nested the other exception
|
||||
*/
|
||||
public UnexpectedInputException(String msg, Throwable nested) {
|
||||
super(msg, nested);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Unchecked exception indicating that an error has occurred while trying to
|
||||
* clear a buffer on a rollback.
|
||||
*
|
||||
* Unchecked exception indicating that an error has occurred while trying to clear a
|
||||
* buffer on a rollback.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Ben Hale
|
||||
*/
|
||||
@@ -26,9 +26,7 @@ package org.springframework.batch.item;
|
||||
public class WriteFailedException extends ItemWriterException {
|
||||
|
||||
/**
|
||||
* Create a new {@link WriteFailedException} based on a message and another
|
||||
* exception.
|
||||
*
|
||||
* Create a new {@link WriteFailedException} based on a message and another exception.
|
||||
* @param message the message for this exception
|
||||
* @param cause the other exception
|
||||
*/
|
||||
@@ -38,7 +36,6 @@ public class WriteFailedException extends ItemWriterException {
|
||||
|
||||
/**
|
||||
* Create a new {@link WriteFailedException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public WriteFailedException(String message) {
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.batch.item;
|
||||
/**
|
||||
* Exception indicating that an {@link ItemWriter} needed to be opened before being
|
||||
* written to.
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -26,7 +26,6 @@ public class WriterNotOpenException extends ItemWriterException {
|
||||
|
||||
/**
|
||||
* Create a new {@link WriterNotOpenException} based on a message.
|
||||
*
|
||||
* @param message the message for this exception
|
||||
*/
|
||||
public WriterNotOpenException(String message) {
|
||||
@@ -34,12 +33,13 @@ public class WriterNotOpenException extends ItemWriterException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link WriterNotOpenException} based on a message and another exception.
|
||||
*
|
||||
* Create a new {@link WriterNotOpenException} based on a message and another
|
||||
* exception.
|
||||
* @param msg the message for this exception
|
||||
* @param nested the other exception
|
||||
*/
|
||||
public WriterNotOpenException(String msg, Throwable nested) {
|
||||
super(msg, nested);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,14 +28,14 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* Superclass for delegating classes which dynamically call a custom method of
|
||||
* injected object. Provides convenient API for dynamic method invocation
|
||||
* shielding subclasses from low-level details and exception handling.
|
||||
* Superclass for delegating classes which dynamically call a custom method of injected
|
||||
* object. Provides convenient API for dynamic method invocation shielding subclasses from
|
||||
* low-level details and exception handling.
|
||||
*
|
||||
* {@link Exception}s thrown by a successfully invoked delegate method are
|
||||
* re-thrown without wrapping. In case the delegate method throws a
|
||||
* {@link Throwable} that doesn't subclass {@link Exception} it will be wrapped
|
||||
* by {@link InvocationTargetThrowableWrapper}.
|
||||
* {@link Exception}s thrown by a successfully invoked delegate method are re-thrown
|
||||
* without wrapping. In case the delegate method throws a {@link Throwable} that doesn't
|
||||
* subclass {@link Exception} it will be wrapped by
|
||||
* {@link InvocationTargetThrowableWrapper}.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
* @author Mahmoud Ben Hassine
|
||||
@@ -49,11 +49,8 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
private Object[] arguments;
|
||||
|
||||
/**
|
||||
* Invoker the target method with arguments set by
|
||||
* {@link #setArguments(Object[])}.
|
||||
*
|
||||
* Invoker the target method with arguments set by {@link #setArguments(Object[])}.
|
||||
* @return object returned by invoked method
|
||||
*
|
||||
* @throws Exception exception thrown when executing the delegate method.
|
||||
*/
|
||||
protected T invokeDelegateMethod() throws Exception {
|
||||
@@ -64,10 +61,8 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
|
||||
/**
|
||||
* Invokes the target method with given argument.
|
||||
*
|
||||
* @param object argument for the target method
|
||||
* @return object returned by target method
|
||||
*
|
||||
* @throws Exception exception thrown when executing the delegate method.
|
||||
*/
|
||||
protected T invokeDelegateMethodWithArgument(Object object) throws Exception {
|
||||
@@ -78,10 +73,8 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
|
||||
/**
|
||||
* Invokes the target method with given arguments.
|
||||
*
|
||||
* @param args arguments for the invoked method
|
||||
* @return object returned by invoked method
|
||||
*
|
||||
* @throws Exception exception thrown when executing the delegate method.
|
||||
*/
|
||||
protected T invokeDelegateMethodWithArguments(Object[] args) throws Exception {
|
||||
@@ -140,8 +133,8 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if target class declares a method matching target method
|
||||
* name with given number of arguments of appropriate type.
|
||||
* @return true if target class declares a method matching target method name with
|
||||
* given number of arguments of appropriate type.
|
||||
*/
|
||||
private boolean targetClassDeclaresTargetMethod() {
|
||||
MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
|
||||
@@ -184,8 +177,8 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetObject the delegate - bean id can be used to set this value
|
||||
* in Spring configuration
|
||||
* @param targetObject the delegate - bean id can be used to set this value in Spring
|
||||
* configuration
|
||||
*/
|
||||
public void setTargetObject(Object targetObject) {
|
||||
this.targetObject = targetObject;
|
||||
@@ -200,15 +193,14 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arguments arguments values for the {
|
||||
* {@link #setTargetMethod(String)}. These will be used only when the
|
||||
* subclass tries to invoke the target method without providing explicit
|
||||
* argument values.
|
||||
* @param arguments arguments values for the { {@link #setTargetMethod(String)}. These
|
||||
* will be used only when the subclass tries to invoke the target method without
|
||||
* providing explicit argument values.
|
||||
*
|
||||
* If arguments are set to not-null value {@link #afterPropertiesSet()} will
|
||||
* check the values are compatible with target method's signature. In case
|
||||
* arguments are null (not set) method signature will not be checked and it
|
||||
* is assumed correct values will be supplied at runtime.
|
||||
* If arguments are set to not-null value {@link #afterPropertiesSet()} will check the
|
||||
* values are compatible with target method's signature. In case arguments are null
|
||||
* (not set) method signature will not be checked and it is assumed correct values
|
||||
* will be supplied at runtime.
|
||||
*/
|
||||
public void setArguments(Object[] arguments) {
|
||||
this.arguments = arguments == null ? null : Arrays.asList(arguments).toArray();
|
||||
@@ -221,7 +213,7 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
protected Object[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to wrap a {@link Throwable} (not an {@link Exception}) thrown by a
|
||||
* reflectively-invoked delegate.
|
||||
@@ -236,4 +228,5 @@ public abstract class AbstractMethodInvokingDelegator<T> implements Initializing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ package org.springframework.batch.item.adapter;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* Indicates an error has been encountered while trying to dynamically invoke a
|
||||
* method e.g. using {@link MethodInvoker}.
|
||||
*
|
||||
* The exception should be caused by a failed invocation of a method, it
|
||||
* shouldn't be used to wrap an exception thrown by successfully invoked method.
|
||||
*
|
||||
* Indicates an error has been encountered while trying to dynamically invoke a method
|
||||
* e.g. using {@link MethodInvoker}.
|
||||
*
|
||||
* The exception should be caused by a failed invocation of a method, it shouldn't be used
|
||||
* to wrap an exception thrown by successfully invoked method.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class DynamicMethodInvocationException extends RuntimeException {
|
||||
@@ -39,4 +39,5 @@ public class DynamicMethodInvocationException extends RuntimeException {
|
||||
public DynamicMethodInvocationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,12 +22,11 @@ import org.springframework.util.MethodInvoker;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* A {@link MethodInvoker} that is a bit relaxed about its arguments. You can
|
||||
* give it arguments in the wrong order or you can give it too many arguments
|
||||
* and it will try and find a method that matches a subset.
|
||||
*
|
||||
* A {@link MethodInvoker} that is a bit relaxed about its arguments. You can give it
|
||||
* arguments in the wrong order or you can give it too many arguments and it will try and
|
||||
* find a method that matches a subset.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public class HippyMethodInvoker extends MethodInvoker {
|
||||
@@ -78,4 +77,5 @@ public class HippyMethodInvoker extends MethodInvoker {
|
||||
return matchingMethod;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Invokes a custom method on a delegate plain old Java object which itself
|
||||
* processes an item.
|
||||
* Invokes a custom method on a delegate plain old Java object which itself processes an
|
||||
* item.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ItemProcessorAdapter<I,O> extends AbstractMethodInvokingDelegator<O> implements ItemProcessor<I,O> {
|
||||
public class ItemProcessorAdapter<I, O> extends AbstractMethodInvokingDelegator<O> implements ItemProcessor<I, O> {
|
||||
|
||||
/**
|
||||
* Invoke the delegate method and return the result.
|
||||
|
||||
@@ -20,8 +20,8 @@ import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Invokes a custom method on a delegate plain old Java object which itself
|
||||
* provides an item.
|
||||
* Invokes a custom method on a delegate plain old Java object which itself provides an
|
||||
* item.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
|
||||
@@ -20,13 +20,11 @@ import java.util.List;
|
||||
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Delegates item processing to a custom method -
|
||||
* passes the item as an argument for the delegate method.
|
||||
* Delegates item processing to a custom method - passes the item as an argument for the
|
||||
* delegate method.
|
||||
*
|
||||
* @see PropertyExtractingDelegatingItemWriter
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class ItemWriterAdapter<T> extends AbstractMethodInvokingDelegator<T> implements ItemWriter<T> {
|
||||
@@ -39,4 +37,3 @@ public class ItemWriterAdapter<T> extends AbstractMethodInvokingDelegator<T> imp
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -25,22 +25,20 @@ import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Delegates processing to a custom method - extracts property values from item
|
||||
* object and uses them as arguments for the delegate method.
|
||||
* Delegates processing to a custom method - extracts property values from item object and
|
||||
* uses them as arguments for the delegate method.
|
||||
*
|
||||
* @see ItemWriterAdapter
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class PropertyExtractingDelegatingItemWriter<T> extends AbstractMethodInvokingDelegator<T> implements
|
||||
ItemWriter<T> {
|
||||
public class PropertyExtractingDelegatingItemWriter<T> extends AbstractMethodInvokingDelegator<T>
|
||||
implements ItemWriter<T> {
|
||||
|
||||
private String[] fieldsUsedAsTargetMethodArguments;
|
||||
|
||||
/**
|
||||
* Extracts values from item's fields named in
|
||||
* fieldsUsedAsTargetMethodArguments and passes them as arguments to the
|
||||
* delegate method.
|
||||
* Extracts values from item's fields named in fieldsUsedAsTargetMethodArguments and
|
||||
* passes them as arguments to the delegate method.
|
||||
*/
|
||||
@Override
|
||||
public void write(List<? extends T> items) throws Exception {
|
||||
@@ -66,13 +64,13 @@ ItemWriter<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fieldsUsedAsMethodArguments the values of the these item's fields
|
||||
* will be used as arguments for the delegate method. Nested property values
|
||||
* are supported, e.g. <code>address.city</code>
|
||||
* @param fieldsUsedAsMethodArguments the values of the these item's fields will be
|
||||
* used as arguments for the delegate method. Nested property values are supported,
|
||||
* e.g. <code>address.city</code>
|
||||
*/
|
||||
public void setFieldsUsedAsTargetMethodArguments(String[] fieldsUsedAsMethodArguments) {
|
||||
this.fieldsUsedAsTargetMethodArguments = Arrays.asList(fieldsUsedAsMethodArguments).toArray(
|
||||
new String[fieldsUsedAsMethodArguments.length]);
|
||||
this.fieldsUsedAsTargetMethodArguments = Arrays.asList(fieldsUsedAsMethodArguments)
|
||||
.toArray(new String[fieldsUsedAsMethodArguments.length]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,21 +24,22 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AMQP {@link ItemReader} implementation using an {@link AmqpTemplate} to
|
||||
* receive and/or convert messages.
|
||||
* AMQP {@link ItemReader} implementation using an {@link AmqpTemplate} to receive and/or
|
||||
* convert messages.
|
||||
* </p>
|
||||
*
|
||||
* @author Chris Schaefer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
public class AmqpItemReader<T> implements ItemReader<T> {
|
||||
|
||||
private final AmqpTemplate amqpTemplate;
|
||||
|
||||
private Class<? extends T> itemType;
|
||||
|
||||
/**
|
||||
* Initialize the AmqpItemReader.
|
||||
*
|
||||
* @param amqpTemplate the template to be used. Must not be null.
|
||||
* @param amqpTemplate the template to be used. Must not be null.
|
||||
*/
|
||||
public AmqpItemReader(final AmqpTemplate amqpTemplate) {
|
||||
Assert.notNull(amqpTemplate, "AmqpTemplate must not be null");
|
||||
@@ -66,11 +67,11 @@ public class AmqpItemReader<T> implements ItemReader<T> {
|
||||
|
||||
/**
|
||||
* Establish the itemType for the reader.
|
||||
*
|
||||
* @param itemType class type that will be returned by the reader.
|
||||
*/
|
||||
public void setItemType(Class<? extends T> itemType) {
|
||||
Assert.notNull(itemType, "Item type cannot be null");
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,32 +26,35 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AMQP {@link ItemWriter} implementation using an {@link AmqpTemplate} to
|
||||
* send messages. Messages will be sent to the nameless exchange if not specified
|
||||
* on the provided {@link AmqpTemplate}.
|
||||
* AMQP {@link ItemWriter} implementation using an {@link AmqpTemplate} to send messages.
|
||||
* Messages will be sent to the nameless exchange if not specified on the provided
|
||||
* {@link AmqpTemplate}.
|
||||
* </p>
|
||||
*
|
||||
* @author Chris Schaefer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
public class AmqpItemWriter<T> implements ItemWriter<T> {
|
||||
private final AmqpTemplate amqpTemplate;
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
public AmqpItemWriter(final AmqpTemplate amqpTemplate) {
|
||||
Assert.notNull(amqpTemplate, "AmqpTemplate must not be null");
|
||||
private final AmqpTemplate amqpTemplate;
|
||||
|
||||
this.amqpTemplate = amqpTemplate;
|
||||
}
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Override
|
||||
public void write(final List<? extends T> items) throws Exception {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Writing to AMQP with " + items.size() + " items.");
|
||||
}
|
||||
public AmqpItemWriter(final AmqpTemplate amqpTemplate) {
|
||||
Assert.notNull(amqpTemplate, "AmqpTemplate must not be null");
|
||||
|
||||
this.amqpTemplate = amqpTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final List<? extends T> items) throws Exception {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Writing to AMQP with " + items.size() + " items.");
|
||||
}
|
||||
|
||||
for (T item : items) {
|
||||
amqpTemplate.convertAndSend(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (T item : items) {
|
||||
amqpTemplate.convertAndSend(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,17 +59,17 @@ public class AmqpItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link AmqpItemReader}.
|
||||
*
|
||||
* @return a {@link AmqpItemReader}
|
||||
*/
|
||||
public AmqpItemReader<T> build() {
|
||||
Assert.notNull(this.amqpTemplate, "amqpTemplate is required.");
|
||||
|
||||
AmqpItemReader<T> reader = new AmqpItemReader<>(this.amqpTemplate);
|
||||
if(this.itemType != null) {
|
||||
if (this.itemType != null) {
|
||||
reader.setItemType(this.itemType);
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
@@ -22,6 +22,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A builder implementation for the {@link AmqpItemWriter}
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @since 4.0
|
||||
* @see AmqpItemWriter
|
||||
@@ -44,7 +45,6 @@ public class AmqpItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link AmqpItemWriter}.
|
||||
*
|
||||
* @return a {@link AmqpItemWriter}
|
||||
*/
|
||||
public AmqpItemWriter<T> build() {
|
||||
|
||||
@@ -1,180 +1,182 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item.avro;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.avro.Schema;
|
||||
import org.apache.avro.file.DataFileStream;
|
||||
import org.apache.avro.generic.GenericDatumReader;
|
||||
import org.apache.avro.generic.GenericRecord;
|
||||
import org.apache.avro.io.BinaryDecoder;
|
||||
import org.apache.avro.io.DatumReader;
|
||||
import org.apache.avro.io.DecoderFactory;
|
||||
import org.apache.avro.reflect.ReflectDatumReader;
|
||||
import org.apache.avro.specific.SpecificDatumReader;
|
||||
import org.apache.avro.specific.SpecificRecordBase;
|
||||
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStreamException;
|
||||
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link ItemReader} that deserializes data from a {@link Resource} containing serialized Avro objects.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 4.2
|
||||
*/
|
||||
public class AvroItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> {
|
||||
|
||||
private boolean embeddedSchema = true;
|
||||
|
||||
private InputStreamReader<T> inputStreamReader;
|
||||
|
||||
private DataFileStream<T> dataFileReader;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
private DatumReader<T> datumReader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param resource the {@link Resource} containing objects serialized with Avro.
|
||||
* @param clazz the data type to be deserialized.
|
||||
*/
|
||||
public AvroItemReader(Resource resource, Class<T> clazz) {
|
||||
Assert.notNull(resource, "'resource' is required.");
|
||||
Assert.notNull(clazz, "'class' is required.");
|
||||
|
||||
try {
|
||||
this.inputStream = resource.getInputStream();
|
||||
this.datumReader = datumReaderForClass(clazz);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data the {@link Resource} containing the data to be read.
|
||||
* @param schema the {@link Resource} containing the Avro schema.
|
||||
*/
|
||||
public AvroItemReader(Resource data, Resource schema) {
|
||||
Assert.notNull(data, "'data' is required.");
|
||||
Assert.state(data.exists(), "'data' " + data.getFilename() +" does not exist.");
|
||||
Assert.notNull(schema, "'schema' is required");
|
||||
Assert.state(schema.exists(), "'schema' " + schema.getFilename() +" does not exist.");
|
||||
try {
|
||||
this.inputStream = data.getInputStream();
|
||||
Schema avroSchema = new Schema.Parser().parse(schema.getInputStream());
|
||||
this.datumReader = new GenericDatumReader<>(avroSchema);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable or enable reading an embedded Avro schema. True by default.
|
||||
* @param embeddedSchema set to false to if the input does not embed an Avro schema.
|
||||
*/
|
||||
public void setEmbeddedSchema(boolean embeddedSchema) {
|
||||
this.embeddedSchema = embeddedSchema;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected T doRead() throws Exception {
|
||||
if (this.inputStreamReader != null) {
|
||||
return this.inputStreamReader.read();
|
||||
}
|
||||
return this.dataFileReader.hasNext()? this.dataFileReader.next(): null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOpen() throws Exception {
|
||||
initializeReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() throws Exception {
|
||||
if (this.inputStreamReader != null) {
|
||||
this.inputStreamReader.close();
|
||||
return;
|
||||
}
|
||||
this.dataFileReader.close();
|
||||
}
|
||||
|
||||
private void initializeReader() throws IOException {
|
||||
if (this.embeddedSchema) {
|
||||
this.dataFileReader = new DataFileStream<>(this.inputStream, this.datumReader);
|
||||
} else {
|
||||
this.inputStreamReader = createInputStreamReader(this.inputStream, this.datumReader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private InputStreamReader<T> createInputStreamReader(InputStream inputStream, DatumReader<T> datumReader) {
|
||||
return new InputStreamReader<>(inputStream, datumReader);
|
||||
}
|
||||
|
||||
private static <T> DatumReader<T> datumReaderForClass(Class<T> clazz) {
|
||||
if (SpecificRecordBase.class.isAssignableFrom(clazz)){
|
||||
return new SpecificDatumReader<>(clazz);
|
||||
}
|
||||
if (GenericRecord.class.isAssignableFrom(clazz)) {
|
||||
return new GenericDatumReader<>();
|
||||
}
|
||||
return new ReflectDatumReader<>(clazz);
|
||||
}
|
||||
|
||||
|
||||
private static class InputStreamReader<T> {
|
||||
private final DatumReader<T> datumReader;
|
||||
|
||||
private final BinaryDecoder binaryDecoder;
|
||||
|
||||
private final InputStream inputStream;
|
||||
|
||||
private InputStreamReader(InputStream inputStream, DatumReader<T> datumReader) {
|
||||
this.inputStream = inputStream;
|
||||
this.datumReader = datumReader;
|
||||
this.binaryDecoder = DecoderFactory.get().binaryDecoder(inputStream, null);
|
||||
}
|
||||
|
||||
private T read() throws Exception {
|
||||
if (!this.binaryDecoder.isEnd()) {
|
||||
return this.datumReader.read(null, this.binaryDecoder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void close() {
|
||||
try {
|
||||
this.inputStream.close();
|
||||
} catch (IOException e) {
|
||||
throw new ItemStreamException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.batch.item.avro;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.avro.Schema;
|
||||
import org.apache.avro.file.DataFileStream;
|
||||
import org.apache.avro.generic.GenericDatumReader;
|
||||
import org.apache.avro.generic.GenericRecord;
|
||||
import org.apache.avro.io.BinaryDecoder;
|
||||
import org.apache.avro.io.DatumReader;
|
||||
import org.apache.avro.io.DecoderFactory;
|
||||
import org.apache.avro.reflect.ReflectDatumReader;
|
||||
import org.apache.avro.specific.SpecificDatumReader;
|
||||
import org.apache.avro.specific.SpecificRecordBase;
|
||||
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStreamException;
|
||||
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link ItemReader} that deserializes data from a {@link Resource} containing
|
||||
* serialized Avro objects.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 4.2
|
||||
*/
|
||||
public class AvroItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> {
|
||||
|
||||
private boolean embeddedSchema = true;
|
||||
|
||||
private InputStreamReader<T> inputStreamReader;
|
||||
|
||||
private DataFileStream<T> dataFileReader;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
private DatumReader<T> datumReader;
|
||||
|
||||
/**
|
||||
* @param resource the {@link Resource} containing objects serialized with Avro.
|
||||
* @param clazz the data type to be deserialized.
|
||||
*/
|
||||
public AvroItemReader(Resource resource, Class<T> clazz) {
|
||||
Assert.notNull(resource, "'resource' is required.");
|
||||
Assert.notNull(clazz, "'class' is required.");
|
||||
|
||||
try {
|
||||
this.inputStream = resource.getInputStream();
|
||||
this.datumReader = datumReaderForClass(clazz);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data the {@link Resource} containing the data to be read.
|
||||
* @param schema the {@link Resource} containing the Avro schema.
|
||||
*/
|
||||
public AvroItemReader(Resource data, Resource schema) {
|
||||
Assert.notNull(data, "'data' is required.");
|
||||
Assert.state(data.exists(), "'data' " + data.getFilename() + " does not exist.");
|
||||
Assert.notNull(schema, "'schema' is required");
|
||||
Assert.state(schema.exists(), "'schema' " + schema.getFilename() + " does not exist.");
|
||||
try {
|
||||
this.inputStream = data.getInputStream();
|
||||
Schema avroSchema = new Schema.Parser().parse(schema.getInputStream());
|
||||
this.datumReader = new GenericDatumReader<>(avroSchema);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable or enable reading an embedded Avro schema. True by default.
|
||||
* @param embeddedSchema set to false to if the input does not embed an Avro schema.
|
||||
*/
|
||||
public void setEmbeddedSchema(boolean embeddedSchema) {
|
||||
this.embeddedSchema = embeddedSchema;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected T doRead() throws Exception {
|
||||
if (this.inputStreamReader != null) {
|
||||
return this.inputStreamReader.read();
|
||||
}
|
||||
return this.dataFileReader.hasNext() ? this.dataFileReader.next() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOpen() throws Exception {
|
||||
initializeReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() throws Exception {
|
||||
if (this.inputStreamReader != null) {
|
||||
this.inputStreamReader.close();
|
||||
return;
|
||||
}
|
||||
this.dataFileReader.close();
|
||||
}
|
||||
|
||||
private void initializeReader() throws IOException {
|
||||
if (this.embeddedSchema) {
|
||||
this.dataFileReader = new DataFileStream<>(this.inputStream, this.datumReader);
|
||||
}
|
||||
else {
|
||||
this.inputStreamReader = createInputStreamReader(this.inputStream, this.datumReader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private InputStreamReader<T> createInputStreamReader(InputStream inputStream, DatumReader<T> datumReader) {
|
||||
return new InputStreamReader<>(inputStream, datumReader);
|
||||
}
|
||||
|
||||
private static <T> DatumReader<T> datumReaderForClass(Class<T> clazz) {
|
||||
if (SpecificRecordBase.class.isAssignableFrom(clazz)) {
|
||||
return new SpecificDatumReader<>(clazz);
|
||||
}
|
||||
if (GenericRecord.class.isAssignableFrom(clazz)) {
|
||||
return new GenericDatumReader<>();
|
||||
}
|
||||
return new ReflectDatumReader<>(clazz);
|
||||
}
|
||||
|
||||
private static class InputStreamReader<T> {
|
||||
|
||||
private final DatumReader<T> datumReader;
|
||||
|
||||
private final BinaryDecoder binaryDecoder;
|
||||
|
||||
private final InputStream inputStream;
|
||||
|
||||
private InputStreamReader(InputStream inputStream, DatumReader<T> datumReader) {
|
||||
this.inputStream = inputStream;
|
||||
this.datumReader = datumReader;
|
||||
this.binaryDecoder = DecoderFactory.get().binaryDecoder(inputStream, null);
|
||||
}
|
||||
|
||||
private T read() throws Exception {
|
||||
if (!this.binaryDecoder.isEnd()) {
|
||||
return this.datumReader.read(null, this.binaryDecoder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void close() {
|
||||
try {
|
||||
this.inputStream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ItemStreamException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,9 +62,7 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
|
||||
private boolean embedSchema = true;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param resource a {@link WritableResource} to which the objects will be serialized.
|
||||
* @param schema a {@link Resource} containing the Avro schema.
|
||||
* @param clazz the data type to be serialized.
|
||||
@@ -77,7 +75,6 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
|
||||
/**
|
||||
* This constructor will create an ItemWriter that does not embedded Avro schema.
|
||||
*
|
||||
* @param resource a {@link WritableResource} to which the objects will be serialized.
|
||||
* @param clazz the data type to be serialized.
|
||||
*/
|
||||
@@ -111,7 +108,8 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
super.open(executionContext);
|
||||
try {
|
||||
initializeWriter();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ItemStreamException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +129,7 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeWriter() throws IOException {
|
||||
private void initializeWriter() throws IOException {
|
||||
Assert.notNull(this.resource, "'resource' is required.");
|
||||
Assert.notNull(this.clazz, "'class' is required.");
|
||||
|
||||
@@ -142,12 +140,14 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
Schema schema;
|
||||
try {
|
||||
schema = new Schema.Parser().parse(this.schemaResource.getInputStream());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
this.dataFileWriter = new DataFileWriter<>(datumWriterForClass(this.clazz));
|
||||
this.dataFileWriter.create(schema, this.resource.getOutputStream());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.outputStreamWriter = createOutputStreamWriter(this.resource.getOutputStream(),
|
||||
datumWriterForClass(this.clazz));
|
||||
}
|
||||
@@ -155,7 +155,7 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
}
|
||||
|
||||
private static <T> DatumWriter<T> datumWriterForClass(Class<T> clazz) {
|
||||
if (SpecificRecordBase.class.isAssignableFrom(clazz)){
|
||||
if (SpecificRecordBase.class.isAssignableFrom(clazz)) {
|
||||
return new SpecificDatumWriter<>(clazz);
|
||||
}
|
||||
if (GenericRecord.class.isAssignableFrom(clazz)) {
|
||||
@@ -170,6 +170,7 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
}
|
||||
|
||||
private static class OutputStreamWriter<T> {
|
||||
|
||||
private final DatumWriter<T> datumWriter;
|
||||
|
||||
private final BinaryEncoder binaryEncoder;
|
||||
@@ -195,5 +196,7 @@ public class AvroItemWriter<T> extends AbstractItemStreamItemWriter<T> {
|
||||
throw new ItemStreamException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,8 +47,7 @@ public class AvroItemReaderBuilder<T> {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private boolean embeddedSchema =true;
|
||||
|
||||
private boolean embeddedSchema = true;
|
||||
|
||||
/**
|
||||
* Configure a {@link Resource} containing Avro serialized objects.
|
||||
@@ -62,7 +61,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure an Avro {@link Schema} from a {@link Resource}.
|
||||
* @param schema an existing schema Resource.
|
||||
@@ -100,7 +98,7 @@ public class AvroItemReaderBuilder<T> {
|
||||
/**
|
||||
* Disable or enable reading an embedded Avro schema. True by default.
|
||||
* @param embeddedSchema set to false to if the input does not contain an Avro schema.
|
||||
* @return The current instance of the builder.
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
public AvroItemReaderBuilder<T> embeddedSchema(boolean embeddedSchema) {
|
||||
this.embeddedSchema = embeddedSchema;
|
||||
@@ -108,10 +106,9 @@ public class AvroItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -124,7 +121,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -136,7 +132,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -148,7 +143,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -158,7 +152,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build an instance of {@link AvroItemReader}.
|
||||
* @return the instance;
|
||||
@@ -177,9 +170,8 @@ public class AvroItemReaderBuilder<T> {
|
||||
|
||||
avroItemReader.setSaveState(this.saveState);
|
||||
|
||||
if(this.saveState) {
|
||||
Assert.state(StringUtils.hasText(this.name),
|
||||
"A name is required when saveState is set to true.");
|
||||
if (this.saveState) {
|
||||
Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true.");
|
||||
}
|
||||
|
||||
avroItemReader.setName(this.name);
|
||||
@@ -190,7 +182,6 @@ public class AvroItemReaderBuilder<T> {
|
||||
return avroItemReader;
|
||||
}
|
||||
|
||||
|
||||
private AvroItemReader<T> buildForType() {
|
||||
Assert.isNull(this.schema, "You cannot specify a schema and 'type'.");
|
||||
return new AvroItemReader<>(this.resource, this.type);
|
||||
@@ -201,5 +192,4 @@ public class AvroItemReaderBuilder<T> {
|
||||
return new AvroItemReader<>(this.resource, this.schema);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -30,16 +30,16 @@ import org.springframework.util.Assert;
|
||||
* @since 4.2
|
||||
*/
|
||||
public class AvroItemWriterBuilder<T> {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private WritableResource resource;
|
||||
|
||||
private Resource schema;
|
||||
|
||||
private String name = AvroItemWriter.class.getSimpleName();
|
||||
private String name = AvroItemWriter.class.getSimpleName();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param resource the {@link WritableResource} used to write the serialized data.
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -50,7 +50,6 @@ public class AvroItemWriterBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param schema the Resource containing the schema JSON used to serialize the output.
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -61,10 +60,9 @@ public class AvroItemWriterBuilder<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param schemaString the String containing the schema JSON used to serialize the output.
|
||||
* @param schemaString the String containing the schema JSON used to serialize the
|
||||
* output.
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
public AvroItemWriterBuilder<T> schema(String schemaString) {
|
||||
@@ -73,9 +71,7 @@ public class AvroItemWriterBuilder<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type the Class of objects to be serialized.
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -88,7 +84,6 @@ public class AvroItemWriterBuilder<T> {
|
||||
/**
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -101,7 +96,6 @@ public class AvroItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Build an instance of {@link AvroItemWriter}.
|
||||
*
|
||||
* @return the instance;
|
||||
*/
|
||||
public AvroItemWriter<T> build() {
|
||||
@@ -110,9 +104,9 @@ public class AvroItemWriterBuilder<T> {
|
||||
|
||||
Assert.notNull(this.type, "A 'type' is required.");
|
||||
|
||||
AvroItemWriter<T> avroItemWriter = this.schema != null ?
|
||||
new AvroItemWriter<>(this.resource, this.schema, this.type):
|
||||
new AvroItemWriter<>(this.resource, this.type);
|
||||
AvroItemWriter<T> avroItemWriter = this.schema != null
|
||||
? new AvroItemWriter<>(this.resource, this.schema, this.type)
|
||||
: new AvroItemWriter<>(this.resource, this.type);
|
||||
avroItemWriter.setName(this.name);
|
||||
return avroItemWriter;
|
||||
}
|
||||
|
||||
@@ -24,17 +24,16 @@ import org.springframework.util.Assert;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A base class that handles basic reading logic based on the paginated
|
||||
* semantics of Spring Data's paginated facilities. It also handles the
|
||||
* semantics required for restartability based on those facilities.
|
||||
*
|
||||
* A base class that handles basic reading logic based on the paginated semantics of
|
||||
* Spring Data's paginated facilities. It also handles the semantics required for
|
||||
* restartability based on those facilities.
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Glenn Renfro
|
||||
* @since 2.2
|
||||
* @param <T> Type of item to be read
|
||||
*/
|
||||
public abstract class AbstractPaginatedDataItemReader<T> extends
|
||||
AbstractItemCountingItemStreamItemReader<T> {
|
||||
public abstract class AbstractPaginatedDataItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> {
|
||||
|
||||
protected volatile int page = 0;
|
||||
|
||||
@@ -46,8 +45,7 @@ AbstractItemCountingItemStreamItemReader<T> {
|
||||
|
||||
/**
|
||||
* The number of items to be read with each page.
|
||||
*
|
||||
* @param pageSize the number of items. pageSize must be greater than zero.
|
||||
* @param pageSize the number of items. pageSize must be greater than zero.
|
||||
*/
|
||||
public void setPageSize(int pageSize) {
|
||||
Assert.isTrue(pageSize > 0, "pageSize must be greater than zero");
|
||||
@@ -59,19 +57,18 @@ AbstractItemCountingItemStreamItemReader<T> {
|
||||
protected T doRead() throws Exception {
|
||||
|
||||
synchronized (lock) {
|
||||
if(results == null || !results.hasNext()) {
|
||||
if (results == null || !results.hasNext()) {
|
||||
|
||||
results = doPageRead();
|
||||
|
||||
page ++;
|
||||
page++;
|
||||
|
||||
if(results == null || !results.hasNext()) {
|
||||
if (results == null || !results.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(results.hasNext()) {
|
||||
if (results.hasNext()) {
|
||||
return results.next();
|
||||
}
|
||||
else {
|
||||
@@ -81,15 +78,12 @@ AbstractItemCountingItemStreamItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method this {@link ItemStreamReader} delegates to
|
||||
* for the actual work of reading a page. Each time
|
||||
* this method is called, the resulting {@link Iterator}
|
||||
* should contain the items read within the next page.
|
||||
* <br><br>
|
||||
* If the {@link Iterator} is empty or null when it is
|
||||
* returned, this {@link ItemReader} will assume that the
|
||||
* input has been exhausted.
|
||||
*
|
||||
* Method this {@link ItemStreamReader} delegates to for the actual work of reading a
|
||||
* page. Each time this method is called, the resulting {@link Iterator} should
|
||||
* contain the items read within the next page. <br>
|
||||
* <br>
|
||||
* If the {@link Iterator} is empty or null when it is returned, this
|
||||
* {@link ItemReader} will assume that the input has been exhausted.
|
||||
* @return an {@link Iterator} containing the items within a page.
|
||||
*/
|
||||
protected abstract Iterator<T> doPageRead();
|
||||
@@ -110,9 +104,10 @@ AbstractItemCountingItemStreamItemReader<T> {
|
||||
|
||||
Iterator<T> initialPage = doPageRead();
|
||||
|
||||
for(; current >= 0; current--) {
|
||||
for (; current >= 0; current--) {
|
||||
initialPage.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://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.
|
||||
@@ -20,13 +20,15 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link ItemWriter} that stores items in GemFire
|
||||
*
|
||||
*
|
||||
* @author David Turanski
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class GemfireItemWriter<K,V> extends KeyValueItemWriter<K,V> {
|
||||
public class GemfireItemWriter<K, V> extends KeyValueItemWriter<K, V> {
|
||||
|
||||
private GemfireOperations gemfireTemplate;
|
||||
|
||||
/**
|
||||
* @param gemfireTemplate the {@link GemfireTemplate} to set
|
||||
*/
|
||||
@@ -34,19 +36,26 @@ public class GemfireItemWriter<K,V> extends KeyValueItemWriter<K,V> {
|
||||
this.gemfireTemplate = gemfireTemplate;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.KeyValueItemWriter#writeKeyValue(java.lang.Object, java.lang.Object)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.KeyValueItemWriter#writeKeyValue(java.lang.Object,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void writeKeyValue(K key, V value) {
|
||||
if (delete) {
|
||||
gemfireTemplate.remove(key);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
gemfireTemplate.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.KeyValueItemWriter#init()
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -41,39 +41,38 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Restartable {@link ItemReader} that reads documents from MongoDB
|
||||
* via a paging technique.
|
||||
* Restartable {@link ItemReader} that reads documents from MongoDB via a paging
|
||||
* technique.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If you set JSON String query {@link #setQuery(String)} then
|
||||
* it executes the JSON to retrieve the requested documents.
|
||||
* If you set JSON String query {@link #setQuery(String)} then it executes the JSON to
|
||||
* retrieve the requested documents.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* If you set Query object {@link #setQuery(Query)} then
|
||||
* it executes the Query to retrieve the requested documents.
|
||||
* If you set Query object {@link #setQuery(Query)} then it executes the Query to retrieve
|
||||
* the requested documents.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The query is executed using paged requests specified in the
|
||||
* {@link #setPageSize(int)}. Additional pages are requested as needed to
|
||||
* provide data when the {@link #read()} method is called.
|
||||
* The query is executed using paged requests specified in the {@link #setPageSize(int)}.
|
||||
* Additional pages are requested as needed to provide data when the {@link #read()}
|
||||
* method is called.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The JSON String query provided supports parameter substitution via ?<index>
|
||||
* placeholders where the <index> indicates the index of the
|
||||
* parameterValue to substitute.
|
||||
* placeholders where the <index> indicates the index of the parameterValue to
|
||||
* substitute.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The implementation is thread-safe between calls to
|
||||
* {@link #open(ExecutionContext)}, but remember to use <code>saveState=false</code>
|
||||
* if used in a multi-threaded client (no restart available).
|
||||
* The implementation is thread-safe between calls to {@link #open(ExecutionContext)}, but
|
||||
* remember to use <code>saveState=false</code> if used in a multi-threaded client (no
|
||||
* restart available).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Takaaki Iida
|
||||
* @author Mahmoud Ben Hassine
|
||||
@@ -82,23 +81,30 @@ import org.springframework.util.StringUtils;
|
||||
public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> implements InitializingBean {
|
||||
|
||||
private MongoOperations template;
|
||||
|
||||
private Query query;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private Class<? extends T> type;
|
||||
|
||||
private Sort sort;
|
||||
|
||||
private String hint;
|
||||
|
||||
private String fields;
|
||||
|
||||
private String collection;
|
||||
|
||||
private List<Object> parameterValues = new ArrayList<>();
|
||||
|
||||
public MongoItemReader() {
|
||||
super();
|
||||
setName(ClassUtils.getShortName(MongoItemReader.class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A Mongo Query to be used.
|
||||
*
|
||||
* @param query Mongo Query to be used.
|
||||
*/
|
||||
public void setQuery(Query query) {
|
||||
@@ -106,9 +112,8 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to perform operations against the MongoDB instance. Also
|
||||
* handles the mapping of documents to objects.
|
||||
*
|
||||
* Used to perform operations against the MongoDB instance. Also handles the mapping
|
||||
* of documents to objects.
|
||||
* @param template the MongoOperations instance to use
|
||||
* @see MongoOperations
|
||||
*/
|
||||
@@ -117,10 +122,9 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* A JSON formatted MongoDB query. Parameterization of the provided query is allowed
|
||||
* A JSON formatted MongoDB query. Parameterization of the provided query is allowed
|
||||
* via ?<index> placeholders where the <index> indicates the index of the
|
||||
* parameterValue to substitute.
|
||||
*
|
||||
* @param queryString JSON formatted Mongo query
|
||||
*/
|
||||
public void setQuery(String queryString) {
|
||||
@@ -129,7 +133,6 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
|
||||
/**
|
||||
* The type of object to be returned for each {@link #read()} call.
|
||||
*
|
||||
* @param type the type of object to return
|
||||
*/
|
||||
public void setTargetType(Class<? extends T> type) {
|
||||
@@ -137,9 +140,8 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link List} of values to be substituted in for each of the
|
||||
* parameters in the query.
|
||||
*
|
||||
* {@link List} of values to be substituted in for each of the parameters in the
|
||||
* query.
|
||||
* @param parameterValues values
|
||||
*/
|
||||
public void setParameterValues(List<Object> parameterValues) {
|
||||
@@ -148,9 +150,7 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON defining the fields to be returned from the matching documents
|
||||
* by MongoDB.
|
||||
*
|
||||
* JSON defining the fields to be returned from the matching documents by MongoDB.
|
||||
* @param fields JSON string that identifies the fields to sort by.
|
||||
*/
|
||||
public void setFields(String fields) {
|
||||
@@ -158,9 +158,9 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Map} of property names/{@link org.springframework.data.domain.Sort.Direction} values to
|
||||
* sort the input by.
|
||||
*
|
||||
* {@link Map} of property
|
||||
* names/{@link org.springframework.data.domain.Sort.Direction} values to sort the
|
||||
* input by.
|
||||
* @param sorts map of properties and direction to sort each.
|
||||
*/
|
||||
public void setSort(Map<String, Sort.Direction> sorts) {
|
||||
@@ -177,7 +177,6 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
|
||||
/**
|
||||
* JSON String telling MongoDB what index to use.
|
||||
*
|
||||
* @param hint string indicating what index to use.
|
||||
*/
|
||||
public void setHint(String hint) {
|
||||
@@ -189,37 +188,40 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
protected Iterator<T> doPageRead() {
|
||||
if (queryString != null) {
|
||||
Pageable pageRequest = PageRequest.of(page, pageSize, sort);
|
||||
|
||||
|
||||
String populatedQuery = replacePlaceholders(queryString, parameterValues);
|
||||
|
||||
|
||||
Query mongoQuery;
|
||||
|
||||
if(StringUtils.hasText(fields)) {
|
||||
|
||||
if (StringUtils.hasText(fields)) {
|
||||
mongoQuery = new BasicQuery(populatedQuery, fields);
|
||||
}
|
||||
else {
|
||||
mongoQuery = new BasicQuery(populatedQuery);
|
||||
}
|
||||
|
||||
|
||||
mongoQuery.with(pageRequest);
|
||||
|
||||
if(StringUtils.hasText(hint)) {
|
||||
|
||||
if (StringUtils.hasText(hint)) {
|
||||
mongoQuery.withHint(hint);
|
||||
}
|
||||
|
||||
if(StringUtils.hasText(collection)) {
|
||||
|
||||
if (StringUtils.hasText(collection)) {
|
||||
return (Iterator<T>) template.find(mongoQuery, type, collection).iterator();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return (Iterator<T>) template.find(mongoQuery, type).iterator();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
else {
|
||||
Pageable pageRequest = PageRequest.of(page, pageSize);
|
||||
query.with(pageRequest);
|
||||
|
||||
if(StringUtils.hasText(collection)) {
|
||||
|
||||
if (StringUtils.hasText(collection)) {
|
||||
return (Iterator<T>) template.find(query, type, collection).iterator();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return (Iterator<T>) template.find(query, type).iterator();
|
||||
}
|
||||
}
|
||||
@@ -235,7 +237,7 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
Assert.state(template != null, "An implementation of MongoOperations is required.");
|
||||
Assert.state(type != null, "A type to convert the input into is required.");
|
||||
Assert.state(queryString != null || query != null, "A query is required.");
|
||||
|
||||
|
||||
if (queryString != null) {
|
||||
Assert.state(sort != null, "A sort is required.");
|
||||
}
|
||||
@@ -257,4 +259,5 @@ public class MongoItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
|
||||
return Sort.by(sortValues);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,15 +40,16 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link ItemWriter} implementation that writes to a MongoDB store using an implementation of Spring Data's
|
||||
* {@link MongoOperations}. Since MongoDB is not a transactional store, a best effort is made to persist
|
||||
* written data at the last moment, yet still honor job status contracts. No attempt to roll back is made
|
||||
* if an error occurs during writing.
|
||||
* A {@link ItemWriter} implementation that writes to a MongoDB store using an
|
||||
* implementation of Spring Data's {@link MongoOperations}. Since MongoDB is not a
|
||||
* transactional store, a best effort is made to persist written data at the last moment,
|
||||
* yet still honor job status contracts. No attempt to roll back is made if an error
|
||||
* occurs during writing.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This writer is thread-safe once all properties are set (normal singleton behavior) so it can be used in multiple
|
||||
* concurrent transactions.
|
||||
* This writer is thread-safe once all properties are set (normal singleton behavior) so
|
||||
* it can be used in multiple concurrent transactions.
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Minella
|
||||
@@ -59,9 +60,13 @@ import org.springframework.util.StringUtils;
|
||||
public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
private static final String ID_KEY = "_id";
|
||||
|
||||
private MongoOperations template;
|
||||
|
||||
private final Object bufferKey;
|
||||
|
||||
private String collection;
|
||||
|
||||
private boolean delete = false;
|
||||
|
||||
public MongoItemWriter() {
|
||||
@@ -70,10 +75,9 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the items being passed to the writer are to be saved or
|
||||
* removed from the data store. If set to false (default), the items will
|
||||
* be saved. If set to true, the items will be removed.
|
||||
*
|
||||
* Indicates if the items being passed to the writer are to be saved or removed from
|
||||
* the data store. If set to false (default), the items will be saved. If set to true,
|
||||
* the items will be removed.
|
||||
* @param delete removal indicator
|
||||
*/
|
||||
public void setDelete(boolean delete) {
|
||||
@@ -82,7 +86,6 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
/**
|
||||
* Set the {@link MongoOperations} to be used to save items to be written.
|
||||
*
|
||||
* @param template the template implementation to be used.
|
||||
*/
|
||||
public void setTemplate(MongoOperations template) {
|
||||
@@ -90,9 +93,8 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link MongoOperations} to be used to save items to be written.
|
||||
* This can be called by a subclass if necessary.
|
||||
*
|
||||
* Get the {@link MongoOperations} to be used to save items to be written. This can be
|
||||
* called by a subclass if necessary.
|
||||
* @return template the template implementation to be used.
|
||||
*/
|
||||
protected MongoOperations getTemplate() {
|
||||
@@ -101,7 +103,6 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
/**
|
||||
* Set the name of the Mongo collection to be written to.
|
||||
*
|
||||
* @param collection the name of the collection.
|
||||
*/
|
||||
public void setCollection(String collection) {
|
||||
@@ -116,7 +117,7 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
*/
|
||||
@Override
|
||||
public void write(List<? extends T> items) throws Exception {
|
||||
if(!transactionActive()) {
|
||||
if (!transactionActive()) {
|
||||
doWrite(items);
|
||||
return;
|
||||
}
|
||||
@@ -126,9 +127,8 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual write to the store via the template.
|
||||
* This can be overridden by a subclass if necessary.
|
||||
*
|
||||
* Performs the actual write to the store via the template. This can be overridden by
|
||||
* a subclass if necessary.
|
||||
* @param items the list of items to be persisted.
|
||||
*/
|
||||
protected void doWrite(List<? extends T> items) {
|
||||
@@ -188,7 +188,7 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<T> getCurrentBuffer() {
|
||||
if(!TransactionSynchronizationManager.hasResource(bufferKey)) {
|
||||
if (!TransactionSynchronizationManager.hasResource(bufferKey)) {
|
||||
TransactionSynchronizationManager.bindResource(bufferKey, new ArrayList<T>());
|
||||
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@@ -196,8 +196,8 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
List<T> items = (List<T>) TransactionSynchronizationManager.getResource(bufferKey);
|
||||
|
||||
if(!CollectionUtils.isEmpty(items)) {
|
||||
if(!readOnly) {
|
||||
if (!CollectionUtils.isEmpty(items)) {
|
||||
if (!readOnly) {
|
||||
doWrite(items);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
if(TransactionSynchronizationManager.hasResource(bufferKey)) {
|
||||
if (TransactionSynchronizationManager.hasResource(bufferKey)) {
|
||||
TransactionSynchronizationManager.unbindResource(bufferKey);
|
||||
}
|
||||
}
|
||||
@@ -219,4 +219,5 @@ public class MongoItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(template != null, "A MongoOperations implementation is required.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,34 +32,33 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Restartable {@link ItemReader} that reads objects from the graph database Neo4j
|
||||
* via a paging technique.
|
||||
* Restartable {@link ItemReader} that reads objects from the graph database Neo4j via a
|
||||
* paging technique.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It executes cypher queries built from the statement fragments provided to
|
||||
* retrieve the requested data. The query is executed using paged requests of
|
||||
* a size specified in {@link #setPageSize(int)}. Additional pages are requested
|
||||
* as needed when the {@link #read()} method is called. On restart, the reader
|
||||
* will begin again at the same number item it left off at.
|
||||
* It executes cypher queries built from the statement fragments provided to retrieve the
|
||||
* requested data. The query is executed using paged requests of a size specified in
|
||||
* {@link #setPageSize(int)}. Additional pages are requested as needed when the
|
||||
* {@link #read()} method is called. On restart, the reader will begin again at the same
|
||||
* number item it left off at.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Performance is dependent on your Neo4J configuration (embedded or remote) as
|
||||
* well as page size. Setting a fairly large page size and using a commit
|
||||
* interval that matches the page size should provide better performance.
|
||||
* Performance is dependent on your Neo4J configuration (embedded or remote) as well as
|
||||
* page size. Setting a fairly large page size and using a commit interval that matches
|
||||
* the page size should provide better performance.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This implementation is thread-safe between calls to
|
||||
* {@link #open(org.springframework.batch.item.ExecutionContext)}, however you
|
||||
* should set <code>saveState=false</code> if used in a multi-threaded
|
||||
* environment (no restart available).
|
||||
* {@link #open(org.springframework.batch.item.ExecutionContext)}, however you should set
|
||||
* <code>saveState=false</code> if used in a multi-threaded environment (no restart
|
||||
* available).
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @deprecated since 5.0 in favor of the item reader from
|
||||
* https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j
|
||||
*/
|
||||
@@ -71,9 +70,13 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
private String startStatement;
|
||||
|
||||
private String returnStatement;
|
||||
|
||||
private String matchStatement;
|
||||
|
||||
private String whereStatement;
|
||||
|
||||
private String orderByStatement;
|
||||
|
||||
private Class<T> targetType;
|
||||
@@ -82,7 +85,6 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
|
||||
/**
|
||||
* Optional parameters to be used in the cypher query.
|
||||
*
|
||||
* @param parameterValues the parameter values to be used in the cypher query
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
@@ -94,10 +96,8 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* The start segment of the cypher query. START is prepended
|
||||
* to the statement provided and should <em>not</em> be
|
||||
* included.
|
||||
*
|
||||
* The start segment of the cypher query. START is prepended to the statement provided
|
||||
* and should <em>not</em> be included.
|
||||
* @param startStatement the start fragment of the cypher query.
|
||||
*/
|
||||
public void setStartStatement(String startStatement) {
|
||||
@@ -105,10 +105,8 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* The return statement of the cypher query. RETURN is prepended
|
||||
* to the statement provided and should <em>not</em> be
|
||||
* included
|
||||
*
|
||||
* The return statement of the cypher query. RETURN is prepended to the statement
|
||||
* provided and should <em>not</em> be included
|
||||
* @param returnStatement the return fragment of the cypher query.
|
||||
*/
|
||||
public void setReturnStatement(String returnStatement) {
|
||||
@@ -116,10 +114,8 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional match fragment of the cypher query. MATCH is
|
||||
* prepended to the statement provided and should <em>not</em>
|
||||
* be included.
|
||||
*
|
||||
* An optional match fragment of the cypher query. MATCH is prepended to the statement
|
||||
* provided and should <em>not</em> be included.
|
||||
* @param matchStatement the match fragment of the cypher query
|
||||
*/
|
||||
public void setMatchStatement(String matchStatement) {
|
||||
@@ -127,10 +123,8 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional where fragment of the cypher query. WHERE is
|
||||
* prepended to the statement provided and should <em>not</em>
|
||||
* be included.
|
||||
*
|
||||
* An optional where fragment of the cypher query. WHERE is prepended to the statement
|
||||
* provided and should <em>not</em> be included.
|
||||
* @param whereStatement where fragment of the cypher query
|
||||
*/
|
||||
public void setWhereStatement(String whereStatement) {
|
||||
@@ -138,11 +132,9 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of properties to order the results by. This is
|
||||
* required so that subsequent page requests pull back the
|
||||
* segment of results correctly. ORDER BY is prepended to
|
||||
* A list of properties to order the results by. This is required so that subsequent
|
||||
* page requests pull back the segment of results correctly. ORDER BY is prepended to
|
||||
* the statement provided and should <em>not</em> be included.
|
||||
*
|
||||
* @param orderByStatement order by fragment of the cypher query.
|
||||
*/
|
||||
public void setOrderByStatement(String orderByStatement) {
|
||||
@@ -163,7 +155,6 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
|
||||
/**
|
||||
* The object type to be returned from each call to {@link #read()}
|
||||
*
|
||||
* @param targetType the type of object to return.
|
||||
*/
|
||||
public void setTargetType(Class<T> targetType) {
|
||||
@@ -201,7 +192,7 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(sessionFactory != null,"A SessionFactory is required");
|
||||
Assert.state(sessionFactory != null, "A SessionFactory is required");
|
||||
Assert.state(targetType != null, "The type to be returned is required");
|
||||
Assert.state(StringUtils.hasText(startStatement), "A START statement is required");
|
||||
Assert.state(StringUtils.hasText(returnStatement), "A RETURN statement is required");
|
||||
@@ -213,15 +204,14 @@ public class Neo4jItemReader<T> extends AbstractPaginatedDataItemReader<T> imple
|
||||
protected Iterator<T> doPageRead() {
|
||||
Session session = getSessionFactory().openSession();
|
||||
|
||||
Iterable<T> queryResults = session.query(getTargetType(),
|
||||
generateLimitCypherQuery(),
|
||||
getParameterValues());
|
||||
Iterable<T> queryResults = session.query(getTargetType(), generateLimitCypherQuery(), getParameterValues());
|
||||
|
||||
if(queryResults != null) {
|
||||
if (queryResults != null) {
|
||||
return queryResults.iterator();
|
||||
}
|
||||
else {
|
||||
return new ArrayList<T>().iterator();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,14 +34,13 @@ import org.springframework.util.CollectionUtils;
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This writer is thread-safe once all properties are set (normal singleton
|
||||
* behavior) so it can be used in multiple concurrent transactions.
|
||||
* This writer is thread-safe once all properties are set (normal singleton behavior) so
|
||||
* it can be used in multiple concurrent transactions.
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Glenn Renfro
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @deprecated since 5.0 in favor of the item writer from
|
||||
* https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j
|
||||
*
|
||||
@@ -49,8 +48,7 @@ import org.springframework.util.CollectionUtils;
|
||||
@Deprecated
|
||||
public class Neo4jItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(Neo4jItemWriter.class);
|
||||
protected static final Log logger = LogFactory.getLog(Neo4jItemWriter.class);
|
||||
|
||||
private boolean delete = false;
|
||||
|
||||
@@ -82,8 +80,7 @@ public class Neo4jItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(this.sessionFactory != null,
|
||||
"A SessionFactory is required");
|
||||
Assert.state(this.sessionFactory != null, "A SessionFactory is required");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,19 +90,18 @@ public class Neo4jItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
*/
|
||||
@Override
|
||||
public void write(List<? extends T> items) throws Exception {
|
||||
if(!CollectionUtils.isEmpty(items)) {
|
||||
if (!CollectionUtils.isEmpty(items)) {
|
||||
doWrite(items);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual write using the template. This can be overridden by
|
||||
* a subclass if necessary.
|
||||
*
|
||||
* Performs the actual write using the template. This can be overridden by a subclass
|
||||
* if necessary.
|
||||
* @param items the list of items to be persisted.
|
||||
*/
|
||||
protected void doWrite(List<? extends T> items) {
|
||||
if(delete) {
|
||||
if (delete) {
|
||||
delete(items);
|
||||
}
|
||||
else {
|
||||
@@ -116,7 +112,7 @@ public class Neo4jItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
private void delete(List<? extends T> items) {
|
||||
Session session = this.sessionFactory.openSession();
|
||||
|
||||
for(T item : items) {
|
||||
for (T item : items) {
|
||||
session.delete(item);
|
||||
}
|
||||
}
|
||||
@@ -128,4 +124,5 @@ public class Neo4jItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
session.save(item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link org.springframework.batch.item.ItemReader} that reads records utilizing
|
||||
* a {@link org.springframework.data.repository.PagingAndSortingRepository}.
|
||||
* A {@link org.springframework.batch.item.ItemReader} that reads records utilizing a
|
||||
* {@link org.springframework.data.repository.PagingAndSortingRepository}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -51,20 +51,24 @@ import org.springframework.util.MethodInvoker;
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The reader must be configured with a {@link org.springframework.data.repository.PagingAndSortingRepository},
|
||||
* a {@link org.springframework.data.domain.Sort}, and a pageSize greater than 0.
|
||||
* The reader must be configured with a
|
||||
* {@link org.springframework.data.repository.PagingAndSortingRepository}, a
|
||||
* {@link org.springframework.data.domain.Sort}, and a pageSize greater than 0.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This implementation is thread-safe between calls to {@link #open(ExecutionContext)}, but remember to use
|
||||
* <code>saveState=false</code> if used in a multi-threaded client (no restart available).
|
||||
* This implementation is thread-safe between calls to {@link #open(ExecutionContext)},
|
||||
* but remember to use <code>saveState=false</code> if used in a multi-threaded client (no
|
||||
* restart available).
|
||||
* </p>
|
||||
*
|
||||
* <p>It is important to note that this is a paging item reader and exceptions that are
|
||||
* <p>
|
||||
* It is important to note that this is a paging item reader and exceptions that are
|
||||
* thrown while reading the page itself (mapping results to objects, etc in the
|
||||
* {@link RepositoryItemReader#doPageRead()}) will not be skippable since this reader has
|
||||
* no way of knowing if an exception should be skipped and therefore will continue to read
|
||||
* the same page until the skip limit is exceeded.</p>
|
||||
* the same page until the skip limit is exceeded.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* NOTE: The {@code RepositoryItemReader} only reads Java Objects i.e. non primitives.
|
||||
@@ -102,7 +106,6 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
|
||||
/**
|
||||
* Arguments to be passed to the data providing method.
|
||||
*
|
||||
* @param arguments list of method arguments to be passed to the repository
|
||||
*/
|
||||
public void setArguments(List<?> arguments) {
|
||||
@@ -111,7 +114,6 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
|
||||
/**
|
||||
* Provides ordering of the results so that order is maintained between paged queries
|
||||
*
|
||||
* @param sorts the fields to sort by and the directions
|
||||
*/
|
||||
public void setSort(Map<String, Sort.Direction> sorts) {
|
||||
@@ -128,7 +130,6 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
/**
|
||||
* The {@link org.springframework.data.repository.PagingAndSortingRepository}
|
||||
* implementation used to read input from.
|
||||
*
|
||||
* @param repository underlying repository for input to be read from.
|
||||
*/
|
||||
public void setRepository(PagingAndSortingRepository<?, ?> repository) {
|
||||
@@ -136,9 +137,8 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies what method on the repository to call. This method must take
|
||||
* Specifies what method on the repository to call. This method must take
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em> argument.
|
||||
*
|
||||
* @param methodName name of the method to invoke
|
||||
*/
|
||||
public void setMethodName(String methodName) {
|
||||
@@ -166,9 +166,9 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
}
|
||||
|
||||
results = doPageRead();
|
||||
page ++;
|
||||
page++;
|
||||
|
||||
if(results.size() <= 0) {
|
||||
if (results.size() <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
}
|
||||
}
|
||||
|
||||
if(current < results.size()) {
|
||||
if (current < results.size()) {
|
||||
T curLine = results.get(current);
|
||||
current++;
|
||||
return curLine;
|
||||
@@ -197,12 +197,11 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual reading of a page via the repository.
|
||||
* Available for overriding as needed.
|
||||
*
|
||||
* Performs the actual reading of a page via the repository. Available for overriding
|
||||
* as needed.
|
||||
* @return the list of items that make up the page
|
||||
* @throws Exception Based on what the underlying method throws or related to the
|
||||
* calling of the method
|
||||
* calling of the method
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<T> doPageRead() throws Exception {
|
||||
@@ -212,7 +211,7 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
|
||||
List<Object> parameters = new ArrayList<>();
|
||||
|
||||
if(arguments != null && arguments.size() > 0) {
|
||||
if (arguments != null && arguments.size() > 0) {
|
||||
parameters.addAll(arguments);
|
||||
}
|
||||
|
||||
@@ -248,7 +247,7 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
return Sort.by(sortValues);
|
||||
}
|
||||
|
||||
private Object doInvoke(MethodInvoker invoker) throws Exception{
|
||||
private Object doInvoke(MethodInvoker invoker) throws Exception {
|
||||
try {
|
||||
invoker.prepare();
|
||||
}
|
||||
@@ -278,4 +277,5 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
|
||||
invoker.setTargetMethod(targetMethod);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,17 +36,18 @@ import org.springframework.util.MethodInvoker;
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* By default, this writer will use {@link CrudRepository#saveAll(Iterable)}
|
||||
* to save items, unless another method is selected with {@link #setMethodName(java.lang.String)}.
|
||||
* It depends on {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)}
|
||||
* method to store the items for the chunk. Performance will be determined by that
|
||||
* implementation more than this writer.
|
||||
* By default, this writer will use {@link CrudRepository#saveAll(Iterable)} to save
|
||||
* items, unless another method is selected with {@link #setMethodName(java.lang.String)}.
|
||||
* It depends on
|
||||
* {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} method to
|
||||
* store the items for the chunk. Performance will be determined by that implementation
|
||||
* more than this writer.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* As long as the repository provided is thread-safe, this writer is also thread-safe once
|
||||
* properties are set (normal singleton behavior), so it can be used in multiple concurrent
|
||||
* transactions.
|
||||
* properties are set (normal singleton behavior), so it can be used in multiple
|
||||
* concurrent transactions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -66,9 +67,8 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* Specifies what method on the repository to call. This method must have the type of
|
||||
* Specifies what method on the repository to call. This method must have the type of
|
||||
* object passed to this writer as the <em>sole</em> argument.
|
||||
*
|
||||
* @param methodName {@link String} containing the method name.
|
||||
*/
|
||||
public void setMethodName(String methodName) {
|
||||
@@ -78,7 +78,6 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
/**
|
||||
* Set the {@link org.springframework.data.repository.CrudRepository} implementation
|
||||
* for persistence
|
||||
*
|
||||
* @param repository the Spring Data repository to be set
|
||||
*/
|
||||
public void setRepository(CrudRepository<T, ?> repository) {
|
||||
@@ -92,24 +91,22 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
*/
|
||||
@Override
|
||||
public void write(List<? extends T> items) throws Exception {
|
||||
if(!CollectionUtils.isEmpty(items)) {
|
||||
if (!CollectionUtils.isEmpty(items)) {
|
||||
doWrite(items);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual write to the repository. This can be overridden by
|
||||
* a subclass if necessary.
|
||||
*
|
||||
* Performs the actual write to the repository. This can be overridden by a subclass
|
||||
* if necessary.
|
||||
* @param items the list of items to be persisted.
|
||||
*
|
||||
* @throws Exception thrown if error occurs during writing.
|
||||
*/
|
||||
protected void doWrite(List<? extends T> items) throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing to the repository with " + items.size() + " items.");
|
||||
}
|
||||
|
||||
|
||||
if (this.methodName == null) {
|
||||
this.repository.saveAll(items);
|
||||
return;
|
||||
@@ -118,7 +115,7 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
MethodInvoker invoker = createMethodInvoker(repository, methodName);
|
||||
|
||||
for (T object : items) {
|
||||
invoker.setArguments(new Object [] {object});
|
||||
invoker.setArguments(new Object[] { object });
|
||||
doInvoke(invoker);
|
||||
}
|
||||
}
|
||||
@@ -137,8 +134,7 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object doInvoke(MethodInvoker invoker) throws Exception{
|
||||
private Object doInvoke(MethodInvoker invoker) throws Exception {
|
||||
try {
|
||||
invoker.prepare();
|
||||
}
|
||||
@@ -171,4 +167,5 @@ public class RepositoryItemWriter<T> implements ItemWriter<T>, InitializingBean
|
||||
invoker.setTargetMethod(targetMethod);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://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.
|
||||
@@ -16,12 +16,14 @@ import org.springframework.batch.item.SpELItemKeyMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A convenient {@link GemfireItemWriter} implementation that uses a {@link SpELItemKeyMapper}
|
||||
*
|
||||
* A convenient {@link GemfireItemWriter} implementation that uses a
|
||||
* {@link SpELItemKeyMapper}
|
||||
*
|
||||
* @author David Turanski
|
||||
* @since 2.2
|
||||
*/
|
||||
public class SpELMappingGemfireItemWriter<K, V> extends GemfireItemWriter<K, V> {
|
||||
|
||||
/**
|
||||
* A constructor that accepts a SpEL expression used to derive the key
|
||||
* @param keyExpression
|
||||
@@ -31,4 +33,5 @@ public class SpELMappingGemfireItemWriter<K, V> extends GemfireItemWriter<K, V>
|
||||
Assert.hasText(keyExpression, "a valid keyExpression is required.");
|
||||
setItemKeyMapper(new SpELItemKeyMapper<>(keyExpression));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ public class GemfireItemWriterBuilder<K, V> {
|
||||
|
||||
/**
|
||||
* Set the {@link Converter} to use to derive the key from the item.
|
||||
*
|
||||
* @param itemKeyMapper the Converter to use.
|
||||
* @return The current instance of the builder.
|
||||
* @see GemfireItemWriter#setItemKeyMapper(Converter)
|
||||
@@ -65,7 +64,6 @@ public class GemfireItemWriterBuilder<K, V> {
|
||||
* Indicates if the items being passed to the writer are to be saved or removed from
|
||||
* the data store. If set to false (default), the items will be saved. If set to true,
|
||||
* the items will be removed.
|
||||
*
|
||||
* @param delete removal indicator.
|
||||
* @return The current instance of the builder.
|
||||
* @see GemfireItemWriter#setDelete(boolean)
|
||||
@@ -76,10 +74,8 @@ public class GemfireItemWriterBuilder<K, V> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link GemfireItemWriter}.
|
||||
*
|
||||
* @return a {@link GemfireItemWriter}
|
||||
*/
|
||||
public GemfireItemWriter<K, V> build() {
|
||||
@@ -92,4 +88,5 @@ public class GemfireItemWriterBuilder<K, V> {
|
||||
writer.setDelete(this.delete);
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
@@ -39,6 +39,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see MongoItemReader
|
||||
*/
|
||||
public class MongoItemReaderBuilder<T> {
|
||||
|
||||
private MongoOperations template;
|
||||
|
||||
private String jsonQuery;
|
||||
@@ -68,10 +69,9 @@ public class MongoItemReaderBuilder<T> {
|
||||
private Query query;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -85,7 +85,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -98,7 +97,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -111,7 +109,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -125,7 +122,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
/**
|
||||
* Used to perform operations against the MongoDB instance. Also handles the mapping
|
||||
* of documents to objects.
|
||||
*
|
||||
* @param template the MongoOperations instance to use
|
||||
* @see MongoOperations
|
||||
* @return The current instance of the builder
|
||||
@@ -138,10 +134,9 @@ public class MongoItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is allowed
|
||||
* via ?<index> placeholders where the <index> indicates the index of the
|
||||
* parameterValue to substitute.
|
||||
*
|
||||
* A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is
|
||||
* allowed via ?<index> placeholders where the <index> indicates the index
|
||||
* of the parameterValue to substitute.
|
||||
* @param query JSON formatted Mongo jsonQuery
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setQuery(String)
|
||||
@@ -154,7 +149,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The type of object to be returned for each {@link MongoItemReader#read()} call.
|
||||
*
|
||||
* @param targetType the type of object to return
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setTargetType(Class)
|
||||
@@ -168,7 +162,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
/**
|
||||
* {@link List} of values to be substituted in for each of the parameters in the
|
||||
* query.
|
||||
*
|
||||
* @param parameterValues values
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setParameterValues(List)
|
||||
@@ -181,7 +174,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Values to be substituted in for each of the parameters in the query.
|
||||
*
|
||||
* @param parameterValues values
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setParameterValues(List)
|
||||
@@ -192,7 +184,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* JSON defining the fields to be returned from the matching documents by MongoDB.
|
||||
*
|
||||
* @param fields JSON string that identifies the fields to sort by.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setFields(String)
|
||||
@@ -207,7 +198,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
* {@link Map} of property
|
||||
* names/{@link org.springframework.data.domain.Sort.Direction} values to sort the
|
||||
* input by.
|
||||
*
|
||||
* @param sorts map of properties and direction to sort each.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setSort(Map)
|
||||
@@ -220,7 +210,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Establish an optional collection that can be queried.
|
||||
*
|
||||
* @param collection Mongo collection to be queried.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setCollection(String)
|
||||
@@ -233,7 +222,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* JSON String telling MongoDB what index to use.
|
||||
*
|
||||
* @param hint string indicating what index to use.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemReader#setHint(String)
|
||||
@@ -246,7 +234,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The number of items to be read with each page.
|
||||
*
|
||||
* @param pageSize the number of items
|
||||
* @return this instance for method chaining
|
||||
* @see MongoItemReader#setPageSize(int)
|
||||
@@ -258,9 +245,8 @@ public class MongoItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a Spring Data Mongo {@link Query}. This will take precedence over a JSON
|
||||
* Provide a Spring Data Mongo {@link Query}. This will take precedence over a JSON
|
||||
* configured query.
|
||||
*
|
||||
* @param query Query to execute
|
||||
* @return this instance for method chaining
|
||||
* @see MongoItemReader#setQuery(Query)
|
||||
@@ -273,7 +259,6 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link MongoItemReader}.
|
||||
*
|
||||
* @return a {@link MongoItemReader}
|
||||
*/
|
||||
public MongoItemReader<T> build() {
|
||||
@@ -307,4 +292,5 @@ public class MongoItemReaderBuilder<T> {
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ public class MongoItemWriterBuilder<T> {
|
||||
* Indicates if the items being passed to the writer are to be saved or removed from
|
||||
* the data store. If set to false (default), the items will be saved. If set to true,
|
||||
* the items will be removed.
|
||||
*
|
||||
* @param delete removal indicator
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemWriter#setDelete(boolean)
|
||||
@@ -52,7 +51,6 @@ public class MongoItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Set the {@link MongoOperations} to be used to save items to be written.
|
||||
*
|
||||
* @param template the template implementation to be used.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemWriter#setTemplate(MongoOperations)
|
||||
@@ -65,11 +63,10 @@ public class MongoItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Set the name of the Mongo collection to be written to.
|
||||
*
|
||||
* @param collection the name of the collection.
|
||||
* @return The current instance of the builder
|
||||
* @see MongoItemWriter#setCollection(String)
|
||||
*
|
||||
*
|
||||
*/
|
||||
public MongoItemWriterBuilder<T> collection(String collection) {
|
||||
this.collection = collection;
|
||||
@@ -79,7 +76,6 @@ public class MongoItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link MongoItemWriter}.
|
||||
*
|
||||
* @return a {@link MongoItemWriter}
|
||||
*/
|
||||
public MongoItemWriter<T> build() {
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.util.Assert;
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 4.0
|
||||
* @see Neo4jItemReader
|
||||
*
|
||||
* @deprecated since 5.0 in favor of the item reader builder from
|
||||
* https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j
|
||||
*/
|
||||
@@ -64,10 +63,9 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -81,7 +79,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -94,7 +91,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -107,7 +103,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -132,7 +127,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The number of items to be read with each page.
|
||||
*
|
||||
* @param pageSize the number of items
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setPageSize(int)
|
||||
@@ -145,7 +139,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Optional parameters to be used in the cypher query.
|
||||
*
|
||||
* @param parameterValues the parameter values to be used in the cypher query
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setParameterValues(Map)
|
||||
@@ -159,7 +152,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
/**
|
||||
* The start segment of the cypher query. START is prepended to the statement provided
|
||||
* and should <em>not</em> be included.
|
||||
*
|
||||
* @param startStatement the start fragment of the cypher query.
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setStartStatement(String)
|
||||
@@ -173,7 +165,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
/**
|
||||
* The return statement of the cypher query. RETURN is prepended to the statement
|
||||
* provided and should <em>not</em> be included
|
||||
*
|
||||
* @param returnStatement the return fragment of the cypher query.
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setReturnStatement(String)
|
||||
@@ -187,7 +178,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
/**
|
||||
* An optional match fragment of the cypher query. MATCH is prepended to the statement
|
||||
* provided and should <em>not</em> be included.
|
||||
*
|
||||
* @param matchStatement the match fragment of the cypher query
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setMatchStatement(String)
|
||||
@@ -201,7 +191,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
/**
|
||||
* An optional where fragment of the cypher query. WHERE is prepended to the statement
|
||||
* provided and should <em>not</em> be included.
|
||||
*
|
||||
* @param whereStatement where fragment of the cypher query
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setWhereStatement(String)
|
||||
@@ -216,7 +205,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
* A list of properties to order the results by. This is required so that subsequent
|
||||
* page requests pull back the segment of results correctly. ORDER BY is prepended to
|
||||
* the statement provided and should <em>not</em> be included.
|
||||
*
|
||||
* @param orderByStatement order by fragment of the cypher query.
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setOrderByStatement(String)
|
||||
@@ -229,7 +217,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The object type to be returned from each call to {@link Neo4jItemReader#read()}
|
||||
*
|
||||
* @param targetType the type of object to return.
|
||||
* @return this instance for method chaining
|
||||
* @see Neo4jItemReader#setTargetType(Class)
|
||||
@@ -242,7 +229,6 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully constructed {@link Neo4jItemReader}.
|
||||
*
|
||||
* @return a new {@link Neo4jItemReader}
|
||||
*/
|
||||
public Neo4jItemReader<T> build() {
|
||||
@@ -256,7 +242,7 @@ public class Neo4jItemReaderBuilder<T> {
|
||||
Assert.hasText(this.orderByStatement, "orderByStatement is required.");
|
||||
Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero");
|
||||
Assert.isTrue(this.maxItemCount > 0, "maxItemCount must be greater than zero");
|
||||
Assert.isTrue(this.maxItemCount > this.currentItemCount , "maxItemCount must be greater than currentItemCount");
|
||||
Assert.isTrue(this.maxItemCount > this.currentItemCount, "maxItemCount must be greater than currentItemCount");
|
||||
|
||||
Neo4jItemReader<T> reader = new Neo4jItemReader<>();
|
||||
reader.setMatchStatement(this.matchStatement);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017-2021 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
@@ -29,7 +29,6 @@ import org.springframework.util.Assert;
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 4.0
|
||||
* @see Neo4jItemWriter
|
||||
*
|
||||
* @deprecated since 5.0 in favor of the item writer builder from
|
||||
* https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j
|
||||
*/
|
||||
@@ -69,7 +68,6 @@ public class Neo4jItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates and builds a {@link org.springframework.batch.item.data.Neo4jItemWriter}.
|
||||
*
|
||||
* @return a {@link Neo4jItemWriter}
|
||||
*/
|
||||
public Neo4jItemWriter<T> build() {
|
||||
@@ -79,4 +77,5 @@ public class Neo4jItemWriterBuilder<T> {
|
||||
writer.setSessionFactory(this.sessionFactory);
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,10 +64,9 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -81,7 +80,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -94,7 +92,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -107,7 +104,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -120,7 +116,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Arguments to be passed to the data providing method.
|
||||
*
|
||||
* @param arguments list of method arguments to be passed to the repository.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setArguments(List)
|
||||
@@ -133,7 +128,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Arguments to be passed to the data providing method.
|
||||
*
|
||||
* @param arguments the method arguments to be passed to the repository.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setArguments(List)
|
||||
@@ -144,7 +138,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Provides ordering of the results so that order is maintained between paged queries.
|
||||
*
|
||||
* @param sorts the fields to sort by and the directions.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setSort(Map)
|
||||
@@ -157,7 +150,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Establish the pageSize for the generated RepositoryItemReader.
|
||||
*
|
||||
* @param pageSize The number of items to retrieve per page.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setPageSize(int)
|
||||
@@ -171,7 +163,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
/**
|
||||
* The {@link org.springframework.data.repository.PagingAndSortingRepository}
|
||||
* implementation used to read input from.
|
||||
*
|
||||
* @param repository underlying repository for input to be read from.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setRepository(PagingAndSortingRepository)
|
||||
@@ -185,7 +176,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
/**
|
||||
* Specifies what method on the repository to call. This method must take
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em> argument.
|
||||
*
|
||||
* @param methodName name of the method to invoke.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemReader#setMethodName(String)
|
||||
@@ -199,13 +189,13 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
/**
|
||||
* Specifies a repository and the type-safe method to call for the reader. The method
|
||||
* configured via this mechanism must take
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em>
|
||||
* argument. This method can be used in place of {@link #repository(PagingAndSortingRepository)},
|
||||
* {@link #methodName(String)}, and {@link #arguments(List)}.
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em> argument.
|
||||
* This method can be used in place of
|
||||
* {@link #repository(PagingAndSortingRepository)}, {@link #methodName(String)}, and
|
||||
* {@link #arguments(List)}.
|
||||
*
|
||||
* Note: The repository that is used by the repositoryMethodReference must be
|
||||
* non-final.
|
||||
*
|
||||
* @param repositoryMethodReference of the used to get a repository and type-safe
|
||||
* method for use by the reader.
|
||||
* @return The current instance of the builder.
|
||||
@@ -221,7 +211,6 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Builds the {@link RepositoryItemReader}.
|
||||
*
|
||||
* @return a {@link RepositoryItemReader}
|
||||
*/
|
||||
public RepositoryItemReader<T> build() {
|
||||
@@ -229,7 +218,7 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
this.methodName = this.repositoryMethodReference.getMethodName();
|
||||
this.repository = this.repositoryMethodReference.getRepository();
|
||||
|
||||
if(CollectionUtils.isEmpty(this.arguments)) {
|
||||
if (CollectionUtils.isEmpty(this.arguments)) {
|
||||
this.arguments = this.repositoryMethodReference.getArguments();
|
||||
}
|
||||
}
|
||||
@@ -257,10 +246,12 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
/**
|
||||
* Establishes a proxy that will capture a the Repository and the associated
|
||||
* methodName that will be used by the reader.
|
||||
* @param <T> The type of repository that will be used by the reader. The class must
|
||||
*
|
||||
* @param <T> The type of repository that will be used by the reader. The class must
|
||||
* not be final.
|
||||
*/
|
||||
public static class RepositoryMethodReference<T> {
|
||||
|
||||
private RepositoryMethodInterceptor repositoryInvocationHandler;
|
||||
|
||||
private PagingAndSortingRepository<?, ?> repository;
|
||||
@@ -294,9 +285,11 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
List<Object> getArguments() {
|
||||
return this.repositoryInvocationHandler.getArguments();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RepositoryMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
private String methodName;
|
||||
|
||||
private List<Object> arguments;
|
||||
@@ -320,5 +313,7 @@ public class RepositoryItemReaderBuilder<T> {
|
||||
List<Object> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.batch.item.data.builder;
|
||||
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -50,7 +49,6 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
/**
|
||||
* Specifies what method on the repository to call. This method must have the type of
|
||||
* object passed to this writer as the <em>sole</em> argument.
|
||||
*
|
||||
* @param methodName the name of the method to be used for saving the item.
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemWriter#setMethodName(String)
|
||||
@@ -64,7 +62,6 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
/**
|
||||
* Set the {@link org.springframework.data.repository.CrudRepository} implementation
|
||||
* for persistence
|
||||
*
|
||||
* @param repository the Spring Data repository to be set
|
||||
* @return The current instance of the builder.
|
||||
* @see RepositoryItemWriter#setRepository(CrudRepository)
|
||||
@@ -78,13 +75,12 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
/**
|
||||
* Specifies a repository and the type-safe method to call for the writer. The method
|
||||
* configured via this mechanism must take
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em>
|
||||
* argument. This method can be used in place of {@link #repository(CrudRepository)},
|
||||
* {@link org.springframework.data.domain.Pageable} as the <em>last</em> argument.
|
||||
* This method can be used in place of {@link #repository(CrudRepository)},
|
||||
* {@link #methodName(String)}}.
|
||||
*
|
||||
* Note: The repository that is used by the repositoryMethodReference must be
|
||||
* non-final.
|
||||
*
|
||||
* @param repositoryMethodReference of the used to get a repository and type-safe
|
||||
* method for use by the writer.
|
||||
* @return The current instance of the builder.
|
||||
@@ -92,7 +88,8 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
* @see RepositoryItemWriter#setRepository(CrudRepository)
|
||||
*
|
||||
*/
|
||||
public RepositoryItemWriterBuilder<T> repository(RepositoryItemWriterBuilder.RepositoryMethodReference repositoryMethodReference) {
|
||||
public RepositoryItemWriterBuilder<T> repository(
|
||||
RepositoryItemWriterBuilder.RepositoryMethodReference repositoryMethodReference) {
|
||||
this.repositoryMethodReference = repositoryMethodReference;
|
||||
|
||||
return this;
|
||||
@@ -100,7 +97,6 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Builds the {@link RepositoryItemWriter}.
|
||||
*
|
||||
* @return a {@link RepositoryItemWriter}
|
||||
*/
|
||||
public RepositoryItemWriter<T> build() {
|
||||
@@ -116,7 +112,8 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
if (this.methodName != null) {
|
||||
Assert.hasText(this.methodName, "methodName must not be empty.");
|
||||
writer.setMethodName(this.methodName);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
logger.debug("No method name provided, CrudRepository.saveAll will be used.");
|
||||
}
|
||||
return writer;
|
||||
@@ -125,10 +122,12 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
/**
|
||||
* Establishes a proxy that will capture a the Repository and the associated
|
||||
* methodName that will be used by the writer.
|
||||
* @param <T> The type of repository that will be used by the writer. The class must
|
||||
*
|
||||
* @param <T> The type of repository that will be used by the writer. The class must
|
||||
* not be final.
|
||||
*/
|
||||
public static class RepositoryMethodReference<T> {
|
||||
|
||||
private RepositoryMethodInterceptor repositoryInvocationHandler;
|
||||
|
||||
private CrudRepository<?, ?> repository;
|
||||
@@ -158,14 +157,15 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
String getMethodName() {
|
||||
return this.repositoryInvocationHandler.getMethodName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RepositoryMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
private String methodName;
|
||||
|
||||
@Override
|
||||
public Object intercept(Object o, Method method, Object[] objects,
|
||||
MethodProxy methodProxy) throws Throwable {
|
||||
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
|
||||
this.methodName = method.getName();
|
||||
return null;
|
||||
}
|
||||
@@ -175,4 +175,5 @@ public class RepositoryItemWriterBuilder<T> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,57 +48,57 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Abstract base class for any simple item reader that opens a database cursor and continually retrieves
|
||||
* the next row in the ResultSet.
|
||||
* Abstract base class for any simple item reader that opens a database cursor and
|
||||
* continually retrieves the next row in the ResultSet.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* By default the cursor will be opened using a separate connection. The ResultSet for the cursor
|
||||
* is held open regardless of commits or roll backs in a surrounding transaction. Clients of this
|
||||
* reader are responsible for buffering the items in the case that they need to be re-presented on a
|
||||
* rollback. This buffering is handled by the step implementations provided and is only a concern for
|
||||
* anyone writing their own step implementations.
|
||||
* By default the cursor will be opened using a separate connection. The ResultSet for the
|
||||
* cursor is held open regardless of commits or roll backs in a surrounding transaction.
|
||||
* Clients of this reader are responsible for buffering the items in the case that they
|
||||
* need to be re-presented on a rollback. This buffering is handled by the step
|
||||
* implementations provided and is only a concern for anyone writing their own step
|
||||
* implementations.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* There is an option ({@link #setUseSharedExtendedConnection(boolean)} that will share the connection
|
||||
* used for the cursor with the rest of the step processing. If you set this flag to <code>true</code>
|
||||
* then you must wrap the DataSource in a {@link ExtendedConnectionDataSourceProxy} to prevent the
|
||||
* connection from being closed and released after each commit performed as part of the step processing.
|
||||
* You must also use a JDBC driver supporting JDBC 3.0 or later since the cursor will be opened with the
|
||||
* There is an option ({@link #setUseSharedExtendedConnection(boolean)} that will share
|
||||
* the connection used for the cursor with the rest of the step processing. If you set
|
||||
* this flag to <code>true</code> then you must wrap the DataSource in a
|
||||
* {@link ExtendedConnectionDataSourceProxy} to prevent the connection from being closed
|
||||
* and released after each commit performed as part of the step processing. You must also
|
||||
* use a JDBC driver supporting JDBC 3.0 or later since the cursor will be opened with the
|
||||
* additional option of 'HOLD_CURSORS_OVER_COMMIT' enabled.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Each call to {@link #read()} will attempt to map the row at the current position in the
|
||||
* ResultSet. There is currently no wrapping of the ResultSet to suppress calls
|
||||
* to next(). However, if the RowMapper (mistakenly) increments the current row,
|
||||
* the next call to read will verify that the current row is at the expected
|
||||
* position and throw a DataAccessException if it is not. The reason for such strictness on the
|
||||
* ResultSet is due to the need to maintain control for transactions and
|
||||
* restartability. This ensures that each call to {@link #read()} returns the
|
||||
* ResultSet at the correct row, regardless of rollbacks or restarts.
|
||||
* ResultSet. There is currently no wrapping of the ResultSet to suppress calls to next().
|
||||
* However, if the RowMapper (mistakenly) increments the current row, the next call to
|
||||
* read will verify that the current row is at the expected position and throw a
|
||||
* DataAccessException if it is not. The reason for such strictness on the ResultSet is
|
||||
* due to the need to maintain control for transactions and restartability. This ensures
|
||||
* that each call to {@link #read()} returns the ResultSet at the correct row, regardless
|
||||
* of rollbacks or restarts.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* {@link ExecutionContext}: The current row is returned as restart data, and
|
||||
* when restored from that same data, the cursor is opened and the current row
|
||||
* set to the value within the restart data. See
|
||||
* {@link #setDriverSupportsAbsolute(boolean)} for improving restart
|
||||
* performance.
|
||||
* {@link ExecutionContext}: The current row is returned as restart data, and when
|
||||
* restored from that same data, the cursor is opened and the current row set to the value
|
||||
* within the restart data. See {@link #setDriverSupportsAbsolute(boolean)} for improving
|
||||
* restart performance.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Calling close on this {@link ItemStream} will cause all resources it is
|
||||
* currently using to be freed. (Connection, ResultSet, etc). It is then illegal
|
||||
* to call {@link #read()} again until it has been re-opened.
|
||||
* Calling close on this {@link ItemStream} will cause all resources it is currently using
|
||||
* to be freed. (Connection, ResultSet, etc). It is then illegal to call {@link #read()}
|
||||
* again until it has been re-opened.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Known limitation: when used with Derby
|
||||
* {@link #setVerifyCursorPosition(boolean)} needs to be <code>false</code>
|
||||
* because {@link ResultSet#getRow()} call used for cursor position verification
|
||||
* is not available for 'TYPE_FORWARD_ONLY' result sets.
|
||||
* Known limitation: when used with Derby {@link #setVerifyCursorPosition(boolean)} needs
|
||||
* to be <code>false</code> because {@link ResultSet#getRow()} call used for cursor
|
||||
* position verification is not available for 'TYPE_FORWARD_ONLY' result sets.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
@@ -109,12 +109,13 @@ import org.springframework.util.Assert;
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
public abstract class AbstractCursorItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
implements InitializingBean {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
public static final int VALUE_NOT_SET = -1;
|
||||
|
||||
private Connection con;
|
||||
|
||||
protected ResultSet rs;
|
||||
@@ -149,9 +150,7 @@ implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Assert that mandatory properties are set.
|
||||
*
|
||||
* @throws IllegalArgumentException if either data source or SQL properties
|
||||
* not set.
|
||||
* @throws IllegalArgumentException if either data source or SQL properties not set.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -160,7 +159,6 @@ implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Public setter for the data source for injection purposes.
|
||||
*
|
||||
* @param dataSource {@link javax.sql.DataSource} to be used
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
@@ -169,7 +167,6 @@ implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Public getter for the data source.
|
||||
*
|
||||
* @return the dataSource
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
@@ -177,12 +174,10 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given JDBC Statement (or PreparedStatement or
|
||||
* CallableStatement), applying statement settings such as fetch size, max
|
||||
* rows, and query timeout. @param stmt the JDBC Statement to prepare
|
||||
*
|
||||
* Prepare the given JDBC Statement (or PreparedStatement or CallableStatement),
|
||||
* applying statement settings such as fetch size, max rows, and query timeout. @param
|
||||
* stmt the JDBC Statement to prepare
|
||||
* @param stmt {@link java.sql.PreparedStatement} to be configured
|
||||
*
|
||||
* @throws SQLException if interactions with provided stmt fail
|
||||
*
|
||||
* @see #setFetchSize
|
||||
@@ -203,13 +198,12 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default SQLErrorCodeSQLExceptionTranslator for the specified
|
||||
* DataSource if none is set.
|
||||
*
|
||||
* Creates a default SQLErrorCodeSQLExceptionTranslator for the specified DataSource
|
||||
* if none is set.
|
||||
* @return the exception translator for this instance.
|
||||
*/
|
||||
protected SQLExceptionTranslator getExceptionTranslator() {
|
||||
synchronized(this) {
|
||||
synchronized (this) {
|
||||
if (exceptionTranslator == null) {
|
||||
if (dataSource != null) {
|
||||
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
|
||||
@@ -231,16 +225,15 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a SQLWarningException if we're not ignoring warnings, else log the
|
||||
* warnings (at debug level).
|
||||
*
|
||||
* @param statement the current statement to obtain the warnings from, if there are any.
|
||||
* Throw a SQLWarningException if we're not ignoring warnings, else log the warnings
|
||||
* (at debug level).
|
||||
* @param statement the current statement to obtain the warnings from, if there are
|
||||
* any.
|
||||
* @throws SQLException if interaction with provided statement fails.
|
||||
*
|
||||
* @see org.springframework.jdbc.SQLWarningException
|
||||
*/
|
||||
protected void handleWarnings(Statement statement) throws SQLWarningException,
|
||||
SQLException {
|
||||
protected void handleWarnings(Statement statement) throws SQLWarningException, SQLException {
|
||||
if (ignoreWarnings) {
|
||||
if (log.isDebugEnabled()) {
|
||||
SQLWarning warningToLog = statement.getWarnings();
|
||||
@@ -260,8 +253,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor in the ResultSet to the position specified by the row
|
||||
* parameter by traversing the ResultSet.
|
||||
* Moves the cursor in the ResultSet to the position specified by the row parameter by
|
||||
* traversing the ResultSet.
|
||||
* @param row The index of the row to move to
|
||||
*/
|
||||
private void moveCursorToRow(int row) {
|
||||
@@ -277,11 +270,9 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be
|
||||
* fetched from the database when more rows are needed for this
|
||||
* <code>ResultSet</code> object. If the fetch size specified is zero, the
|
||||
* JDBC driver ignores the value.
|
||||
*
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be fetched from
|
||||
* the database when more rows are needed for this <code>ResultSet</code> object. If
|
||||
* the fetch size specified is zero, the JDBC driver ignores the value.
|
||||
* @param fetchSize the number of rows to fetch
|
||||
* @see ResultSet#setFetchSize(int)
|
||||
*/
|
||||
@@ -290,9 +281,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the limit for the maximum number of rows that any
|
||||
* <code>ResultSet</code> object can contain to the given number.
|
||||
*
|
||||
* Sets the limit for the maximum number of rows that any <code>ResultSet</code>
|
||||
* object can contain to the given number.
|
||||
* @param maxRows the new max rows limit; zero means there is no limit
|
||||
* @see Statement#setMaxRows(int)
|
||||
*/
|
||||
@@ -301,12 +291,11 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of seconds the driver will wait for a
|
||||
* <code>Statement</code> object to execute to the given number of seconds.
|
||||
* If the limit is exceeded, an <code>SQLException</code> is thrown.
|
||||
*
|
||||
* @param queryTimeout seconds the new query timeout limit in seconds; zero
|
||||
* means there is no limit
|
||||
* Sets the number of seconds the driver will wait for a <code>Statement</code> object
|
||||
* to execute to the given number of seconds. If the limit is exceeded, an
|
||||
* <code>SQLException</code> is thrown.
|
||||
* @param queryTimeout seconds the new query timeout limit in seconds; zero means
|
||||
* there is no limit
|
||||
* @see Statement#setQueryTimeout(int)
|
||||
*/
|
||||
public void setQueryTimeout(int queryTimeout) {
|
||||
@@ -314,9 +303,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether SQLWarnings should be ignored (only logged) or exception
|
||||
* should be thrown.
|
||||
*
|
||||
* Set whether SQLWarnings should be ignored (only logged) or exception should be
|
||||
* thrown.
|
||||
* @param ignoreWarnings if TRUE, warnings are ignored
|
||||
*/
|
||||
public void setIgnoreWarnings(boolean ignoreWarnings) {
|
||||
@@ -324,9 +312,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow verification of cursor position after current row is processed by
|
||||
* RowMapper or RowCallbackHandler. Default value is TRUE.
|
||||
*
|
||||
* Allow verification of cursor position after current row is processed by RowMapper
|
||||
* or RowCallbackHandler. Default value is TRUE.
|
||||
* @param verifyCursorPosition if true, cursor position is verified
|
||||
*/
|
||||
public void setVerifyCursorPosition(boolean verifyCursorPosition) {
|
||||
@@ -335,13 +322,11 @@ implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Indicate whether the JDBC driver supports setting the absolute row on a
|
||||
* {@link ResultSet}. It is recommended that this is set to
|
||||
* <code>true</code> for JDBC drivers that supports ResultSet.absolute() as
|
||||
* it may improve performance, especially if a step fails while working with
|
||||
* a large data set.
|
||||
* {@link ResultSet}. It is recommended that this is set to <code>true</code> for JDBC
|
||||
* drivers that supports ResultSet.absolute() as it may improve performance,
|
||||
* especially if a step fails while working with a large data set.
|
||||
*
|
||||
* @see ResultSet#absolute(int)
|
||||
*
|
||||
* @param driverSupportsAbsolute <code>false</code> by default
|
||||
*/
|
||||
public void setDriverSupportsAbsolute(boolean driverSupportsAbsolute) {
|
||||
@@ -349,19 +334,19 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the connection used for the cursor should be used by all other processing
|
||||
* thus sharing the same transaction. If this is set to false, which is the default, then the
|
||||
* cursor will be opened using in its connection and will not participate in any transactions
|
||||
* started for the rest of the step processing. If you set this flag to true then you must
|
||||
* wrap the DataSource in a {@link ExtendedConnectionDataSourceProxy} to prevent the
|
||||
* connection from being closed and released after each commit.
|
||||
*
|
||||
* When you set this option to <code>true</code> then the statement used to open the cursor
|
||||
* will be created with both 'READ_ONLY' and 'HOLD_CURSORS_OVER_COMMIT' options. This allows
|
||||
* holding the cursor open over transaction start and commits performed in the step processing.
|
||||
* To use this feature you need a database that supports this and a JDBC driver supporting
|
||||
* JDBC 3.0 or later.
|
||||
* Indicate whether the connection used for the cursor should be used by all other
|
||||
* processing thus sharing the same transaction. If this is set to false, which is the
|
||||
* default, then the cursor will be opened using in its connection and will not
|
||||
* participate in any transactions started for the rest of the step processing. If you
|
||||
* set this flag to true then you must wrap the DataSource in a
|
||||
* {@link ExtendedConnectionDataSourceProxy} to prevent the connection from being
|
||||
* closed and released after each commit.
|
||||
*
|
||||
* When you set this option to <code>true</code> then the statement used to open the
|
||||
* cursor will be created with both 'READ_ONLY' and 'HOLD_CURSORS_OVER_COMMIT'
|
||||
* options. This allows holding the cursor open over transaction start and commits
|
||||
* performed in the step processing. To use this feature you need a database that
|
||||
* supports this and a JDBC driver supporting JDBC 3.0 or later.
|
||||
* @param useSharedExtendedConnection <code>false</code> by default
|
||||
*/
|
||||
public void setUseSharedExtendedConnection(boolean useSharedExtendedConnection) {
|
||||
@@ -373,9 +358,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether "autoCommit" should be overridden for the connection used by the cursor. If not set, defaults to
|
||||
* Connection / Datasource default configuration.
|
||||
*
|
||||
* Set whether "autoCommit" should be overridden for the connection used by the
|
||||
* cursor. If not set, defaults to Connection / Datasource default configuration.
|
||||
* @param autoCommit value used for {@link Connection#setAutoCommit(boolean)}.
|
||||
* @since 4.0
|
||||
*/
|
||||
@@ -386,8 +370,8 @@ implements InitializingBean {
|
||||
public abstract String getSql();
|
||||
|
||||
/**
|
||||
* Check the result set is in sync with the currentRow attribute. This is
|
||||
* important to ensure that the user hasn't modified the current row.
|
||||
* Check the result set is in sync with the currentRow attribute. This is important to
|
||||
* ensure that the user hasn't modified the current row.
|
||||
*/
|
||||
private void verifyCursorPosition(long expectedCurrentRow) throws SQLException {
|
||||
if (verifyCursorPosition) {
|
||||
@@ -398,8 +382,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the cursor and database connection. Make call to cleanupOnClose so sub classes can cleanup
|
||||
* any resources they have allocated.
|
||||
* Close the cursor and database connection. Make call to cleanupOnClose so sub
|
||||
* classes can cleanup any resources they have allocated.
|
||||
*/
|
||||
@Override
|
||||
protected void doClose() throws Exception {
|
||||
@@ -408,12 +392,12 @@ implements InitializingBean {
|
||||
rs = null;
|
||||
cleanupOnClose(con);
|
||||
|
||||
if(this.con != null && !this.con.isClosed()) {
|
||||
if (this.con != null && !this.con.isClosed()) {
|
||||
this.con.setAutoCommit(this.initialConnectionAutoCommit);
|
||||
}
|
||||
|
||||
if (useSharedExtendedConnection && dataSource instanceof ExtendedConnectionDataSourceProxy) {
|
||||
((ExtendedConnectionDataSourceProxy)dataSource).stopCloseSuppression(this.con);
|
||||
((ExtendedConnectionDataSourceProxy) dataSource).stopCloseSuppression(this.con);
|
||||
if (!TransactionSynchronizationManager.isActualTransactionActive()) {
|
||||
DataSourceUtils.releaseConnection(con, dataSource);
|
||||
}
|
||||
@@ -428,7 +412,7 @@ implements InitializingBean {
|
||||
* @param connection to the database
|
||||
* @throws Exception If unable to clean up resources
|
||||
*/
|
||||
protected abstract void cleanupOnClose(Connection connection) throws Exception;
|
||||
protected abstract void cleanupOnClose(Connection connection) throws Exception;
|
||||
|
||||
/**
|
||||
* Execute the statement to open the cursor.
|
||||
@@ -452,11 +436,11 @@ implements InitializingBean {
|
||||
if (useSharedExtendedConnection) {
|
||||
if (!(getDataSource() instanceof ExtendedConnectionDataSourceProxy)) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"You must use a ExtendedConnectionDataSourceProxy for the dataSource when " +
|
||||
"useSharedExtendedConnection is set to true.");
|
||||
"You must use a ExtendedConnectionDataSourceProxy for the dataSource when "
|
||||
+ "useSharedExtendedConnection is set to true.");
|
||||
}
|
||||
this.con = DataSourceUtils.getConnection(dataSource);
|
||||
((ExtendedConnectionDataSourceProxy)dataSource).startCloseSuppression(this.con);
|
||||
((ExtendedConnectionDataSourceProxy) dataSource).startCloseSuppression(this.con);
|
||||
}
|
||||
else {
|
||||
this.con = dataSource.getConnection();
|
||||
@@ -502,9 +486,8 @@ implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the cursor and map to the type of object this reader should return. This method must be
|
||||
* overridden by subclasses.
|
||||
*
|
||||
* Read the cursor and map to the type of object this reader should return. This
|
||||
* method must be overridden by subclasses.
|
||||
* @param rs The current result set
|
||||
* @param currentRow Current position of the result set
|
||||
* @return the mapped object at the cursor position
|
||||
@@ -514,8 +497,8 @@ implements InitializingBean {
|
||||
protected abstract T readCursor(ResultSet rs, int currentRow) throws SQLException;
|
||||
|
||||
/**
|
||||
* Use {@link ResultSet#absolute(int)} if possible, otherwise scroll by
|
||||
* calling {@link ResultSet#next()}.
|
||||
* Use {@link ResultSet#absolute(int)} if possible, otherwise scroll by calling
|
||||
* {@link ResultSet#next()}.
|
||||
*/
|
||||
@Override
|
||||
protected void jumpToItem(int itemIndex) throws Exception {
|
||||
|
||||
@@ -30,18 +30,18 @@ import org.springframework.util.ClassUtils;
|
||||
* reading database records in a paging fashion.
|
||||
*
|
||||
* <p>
|
||||
* Implementations should execute queries using paged requests of a size
|
||||
* specified in {@link #setPageSize(int)}. Additional pages are requested when
|
||||
* needed as {@link #read()} method is called, returning an object corresponding
|
||||
* to current position.
|
||||
* Implementations should execute queries using paged requests of a size specified in
|
||||
* {@link #setPageSize(int)}. Additional pages are requested when needed as
|
||||
* {@link #read()} method is called, returning an object corresponding to current
|
||||
* position.
|
||||
* </p>
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractPagingItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
public abstract class AbstractPagingItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -79,7 +79,6 @@ public abstract class AbstractPagingItemReader<T> extends AbstractItemCountingIt
|
||||
|
||||
/**
|
||||
* The number of rows to retrieve at a time.
|
||||
*
|
||||
* @param pageSize the number of rows to fetch per page
|
||||
*/
|
||||
public void setPageSize(int pageSize) {
|
||||
|
||||
@@ -19,8 +19,9 @@ import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
|
||||
/**
|
||||
* A convenient implementation for providing BeanPropertySqlParameterSource when the item has JavaBean properties
|
||||
* that correspond to names used for parameters in the SQL statement.
|
||||
* A convenient implementation for providing BeanPropertySqlParameterSource when the item
|
||||
* has JavaBean properties that correspond to names used for parameters in the SQL
|
||||
* statement.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @since 2.0
|
||||
@@ -28,8 +29,8 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
public class BeanPropertyItemSqlParameterSourceProvider<T> implements ItemSqlParameterSourceProvider<T> {
|
||||
|
||||
/**
|
||||
* Provide parameter values in an {@link BeanPropertySqlParameterSource} based on values from
|
||||
* the provided item.
|
||||
* Provide parameter values in an {@link BeanPropertySqlParameterSource} based on
|
||||
* values from the provided item.
|
||||
* @param item the item to use for parameter values
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -37,43 +37,39 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* Implementation of {@link SmartDataSource} that is capable of keeping a single
|
||||
* JDBC Connection which is NOT closed after each use even if
|
||||
* {@link Connection#close()} is called.
|
||||
* Implementation of {@link SmartDataSource} that is capable of keeping a single JDBC
|
||||
* Connection which is NOT closed after each use even if {@link Connection#close()} is
|
||||
* called.
|
||||
*
|
||||
* The connection can be kept open over multiple transactions when used together
|
||||
* with any of Spring's
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager}
|
||||
* The connection can be kept open over multiple transactions when used together with any
|
||||
* of Spring's {@link org.springframework.transaction.PlatformTransactionManager}
|
||||
* implementations.
|
||||
*
|
||||
* <p>
|
||||
* Loosely based on the SingleConnectionDataSource implementation in Spring
|
||||
* Core. Intended to be used with the {@link JdbcCursorItemReader} to provide a
|
||||
* connection that remains open across transaction boundaries, It remains open
|
||||
* for the life of the cursor, and can be shared with the main transaction of
|
||||
* the rest of the step processing.
|
||||
* Loosely based on the SingleConnectionDataSource implementation in Spring Core. Intended
|
||||
* to be used with the {@link JdbcCursorItemReader} to provide a connection that remains
|
||||
* open across transaction boundaries, It remains open for the life of the cursor, and can
|
||||
* be shared with the main transaction of the rest of the step processing.
|
||||
*
|
||||
* <p>
|
||||
* Once close suppression has been turned on for a connection, it will be
|
||||
* returned for the first {@link #getConnection()} call. Any subsequent calls to
|
||||
* {@link #getConnection()} will retrieve a new connection from the wrapped
|
||||
* {@link DataSource} until the {@link DataSourceUtils} queries whether the
|
||||
* connection should be closed or not by calling
|
||||
* {@link #shouldClose(Connection)} for the close-suppressed {@link Connection}.
|
||||
* At that point the cycle starts over again, and the next
|
||||
* {@link #getConnection()} call will have the {@link Connection} that is being
|
||||
* close-suppressed returned. This allows the use of the close-suppressed
|
||||
* {@link Connection} to be the main {@link Connection} for an extended data
|
||||
* access process. The close suppression is turned off by calling
|
||||
* Once close suppression has been turned on for a connection, it will be returned for the
|
||||
* first {@link #getConnection()} call. Any subsequent calls to {@link #getConnection()}
|
||||
* will retrieve a new connection from the wrapped {@link DataSource} until the
|
||||
* {@link DataSourceUtils} queries whether the connection should be closed or not by
|
||||
* calling {@link #shouldClose(Connection)} for the close-suppressed {@link Connection}.
|
||||
* At that point the cycle starts over again, and the next {@link #getConnection()} call
|
||||
* will have the {@link Connection} that is being close-suppressed returned. This allows
|
||||
* the use of the close-suppressed {@link Connection} to be the main {@link Connection}
|
||||
* for an extended data access process. The close suppression is turned off by calling
|
||||
* {@link #stopCloseSuppression(Connection)}.
|
||||
*
|
||||
* <p>
|
||||
* This class is not multi-threading capable.
|
||||
*
|
||||
* <p>
|
||||
* The connection returned will be a close-suppressing proxy instead of the
|
||||
* physical {@link Connection}. Be aware that you will not be able to cast this
|
||||
* to a native <code>OracleConnection</code> or the like anymore; you'd be required to use
|
||||
* The connection returned will be a close-suppressing proxy instead of the physical
|
||||
* {@link Connection}. Be aware that you will not be able to cast this to a native
|
||||
* <code>OracleConnection</code> or the like anymore; you'd be required to use
|
||||
* {@link java.sql.Connection#unwrap(Class)}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
@@ -104,9 +100,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that takes as a parameter with the {@link DataSource} to be
|
||||
* wrapped.
|
||||
*
|
||||
* Constructor that takes as a parameter with the {@link DataSource} to be wrapped.
|
||||
* @param dataSource DataSource to be used
|
||||
*/
|
||||
public ExtendedConnectionDataSourceProxy(DataSource dataSource) {
|
||||
@@ -115,7 +109,6 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
|
||||
/**
|
||||
* Setter for the {@link DataSource} that is to be wrapped.
|
||||
*
|
||||
* @param dataSource the DataSource
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
@@ -137,9 +130,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
/**
|
||||
* Return the status of close suppression being activated for a given
|
||||
* {@link Connection}
|
||||
*
|
||||
* @param connection the {@link Connection} that the close suppression
|
||||
* status is requested for
|
||||
* @param connection the {@link Connection} that the close suppression status is
|
||||
* requested for
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isCloseSuppressionActive(Connection connection) {
|
||||
@@ -147,9 +139,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param connection the {@link Connection} that close suppression is
|
||||
* requested for
|
||||
* @param connection the {@link Connection} that close suppression is requested for
|
||||
*/
|
||||
public void startCloseSuppression(Connection connection) {
|
||||
synchronized (this.connectionMonitor) {
|
||||
@@ -161,9 +151,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param connection the {@link Connection} that close suppression should be
|
||||
* turned off for
|
||||
* @param connection the {@link Connection} that close suppression should be turned
|
||||
* off for
|
||||
*/
|
||||
public void stopCloseSuppression(Connection connection) {
|
||||
synchronized (this.connectionMonitor) {
|
||||
@@ -232,8 +221,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given Connection with a proxy that delegates every method call
|
||||
* to it but suppresses close calls.
|
||||
* Wrap the given Connection with a proxy that delegates every method call to it but
|
||||
* suppresses close calls.
|
||||
* @param target the original Connection to wrap
|
||||
* @return the wrapped Connection
|
||||
*/
|
||||
@@ -243,9 +232,9 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
* Invocation handler that suppresses close calls on JDBC Connections until
|
||||
* the associated instance of the ExtendedConnectionDataSourceProxy
|
||||
* determines the connection should actually be closed.
|
||||
* Invocation handler that suppresses close calls on JDBC Connections until the
|
||||
* associated instance of the ExtendedConnectionDataSourceProxy determines the
|
||||
* connection should actually be closed.
|
||||
*/
|
||||
private static class CloseSuppressingInvocationHandler implements InvocationHandler {
|
||||
|
||||
@@ -263,26 +252,26 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
// Invocation on ConnectionProxy interface coming in...
|
||||
|
||||
switch (method.getName()) {
|
||||
case "equals":
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
|
||||
case "hashCode":
|
||||
// Use hashCode of Connection proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
case "close":
|
||||
// Handle close method: don't pass the call on if we are
|
||||
// suppressing close calls.
|
||||
if (dataSource.completeCloseCall((Connection) proxy)) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
target.close();
|
||||
return null;
|
||||
}
|
||||
case "getTargetConnection":
|
||||
// Handle getTargetConnection method: return underlying
|
||||
// Connection.
|
||||
return this.target;
|
||||
case "equals":
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
|
||||
case "hashCode":
|
||||
// Use hashCode of Connection proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
case "close":
|
||||
// Handle close method: don't pass the call on if we are
|
||||
// suppressing close calls.
|
||||
if (dataSource.completeCloseCall((Connection) proxy)) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
target.close();
|
||||
return null;
|
||||
}
|
||||
case "getTargetConnection":
|
||||
// Handle getTargetConnection method: return underlying
|
||||
// Connection.
|
||||
return this.target;
|
||||
}
|
||||
|
||||
// Invoke method on target Connection.
|
||||
@@ -293,11 +282,12 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs only a 'shallow' non-recursive check of self's and delegate's
|
||||
* class to retain Java 5 compatibility.
|
||||
* Performs only a 'shallow' non-recursive check of self's and delegate's class to
|
||||
* retain Java 5 compatibility.
|
||||
*/
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
@@ -305,9 +295,9 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either self or delegate (in this order) if one of them can be
|
||||
* cast to supplied parameter class. Does *not* support recursive unwrapping
|
||||
* of the delegate to retain Java 5 compatibility.
|
||||
* Returns either self or delegate (in this order) if one of them can be cast to
|
||||
* supplied parameter class. Does *not* support recursive unwrapping of the delegate
|
||||
* to retain Java 5 compatibility.
|
||||
*/
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
@@ -332,7 +322,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
/**
|
||||
* Added due to JDK 7 compatibility.
|
||||
*/
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException{
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
MethodInvoker invoker = new MethodInvoker();
|
||||
invoker.setTargetObject(dataSource);
|
||||
invoker.setTargetMethod("getParentLogger");
|
||||
@@ -340,8 +330,11 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
|
||||
try {
|
||||
invoker.prepare();
|
||||
return (Logger) invoker.invoke();
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException nsme) {
|
||||
}
|
||||
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
|
||||
| InvocationTargetException nsme) {
|
||||
throw new SQLFeatureNotSupportedException(nsme);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,21 +33,19 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ItemStreamReader} for reading database records built on top of Hibernate. It
|
||||
* executes the HQL query when initialized iterates over the result set as
|
||||
* {@link #read()} method is called, returning an object corresponding to
|
||||
* current row. The query can be set directly using
|
||||
* {@link #setQueryString(String)}, a named query can be used by
|
||||
* {@link #setQueryName(String)}, or a query provider strategy can be supplied
|
||||
* via {@link #setQueryProvider(HibernateQueryProvider)}.
|
||||
* executes the HQL query when initialized iterates over the result set as {@link #read()}
|
||||
* method is called, returning an object corresponding to current row. The query can be
|
||||
* set directly using {@link #setQueryString(String)}, a named query can be used by
|
||||
* {@link #setQueryName(String)}, or a query provider strategy can be supplied via
|
||||
* {@link #setQueryProvider(HibernateQueryProvider)}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The reader can be configured to use either {@link StatelessSession}
|
||||
* sufficient for simple mappings without the need to cascade to associated
|
||||
* objects or standard hibernate {@link Session} for more advanced mappings or
|
||||
* when caching is desired. When stateful session is used it will be cleared in
|
||||
* the {@link #update(ExecutionContext)} method without being flushed (no data
|
||||
* modifications are expected).
|
||||
* The reader can be configured to use either {@link StatelessSession} sufficient for
|
||||
* simple mappings without the need to cascade to associated objects or standard hibernate
|
||||
* {@link Session} for more advanced mappings or when caching is desired. When stateful
|
||||
* session is used it will be cleared in the {@link #update(ExecutionContext)} method
|
||||
* without being flushed (no data modifications are expected).
|
||||
* </p>
|
||||
*
|
||||
* The implementation is <b>not</b> thread-safe.
|
||||
@@ -55,8 +53,8 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
|
||||
private HibernateItemReaderHelper<T> helper = new HibernateItemReaderHelper<>();
|
||||
|
||||
@@ -80,7 +78,6 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
|
||||
/**
|
||||
* The parameter values to apply to a query (map of name:value).
|
||||
*
|
||||
* @param parameterValues the parameter values to set
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
@@ -90,9 +87,7 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
/**
|
||||
* A query name for an externalized query. Either this or the {
|
||||
* {@link #setQueryString(String) query string} or the {
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} should
|
||||
* be set.
|
||||
*
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} should be set.
|
||||
* @param queryName name of a hibernate named query
|
||||
*/
|
||||
public void setQueryName(String queryName) {
|
||||
@@ -100,9 +95,8 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched
|
||||
* from database per round trip.
|
||||
*
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched from
|
||||
* database per round trip.
|
||||
* @param fetchSize the fetch size to pass down to Hibernate
|
||||
*/
|
||||
public void setFetchSize(int fetchSize) {
|
||||
@@ -110,10 +104,8 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. Either this or the {{@link #setQueryString(String)
|
||||
* query string} or the {{@link #setQueryName(String) query name} should be
|
||||
* set.
|
||||
*
|
||||
* A query provider. Either this or the {{@link #setQueryString(String) query string}
|
||||
* or the {{@link #setQueryName(String) query name} should be set.
|
||||
* @param queryProvider Hibernate query provider
|
||||
*/
|
||||
public void setQueryProvider(HibernateQueryProvider<T> queryProvider) {
|
||||
@@ -124,7 +116,6 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
* A query string in HQL. Either this or the {
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} or the {
|
||||
* {@link #setQueryName(String) query name} should be set.
|
||||
*
|
||||
* @param queryString HQL query string
|
||||
*/
|
||||
public void setQueryString(String queryString) {
|
||||
@@ -133,7 +124,6 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
|
||||
/**
|
||||
* The Hibernate SessionFactory to use the create a session.
|
||||
*
|
||||
* @param sessionFactory the {@link SessionFactory} to set
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
@@ -142,10 +132,8 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
|
||||
/**
|
||||
* Can be set only in uninitialized state.
|
||||
*
|
||||
* @param useStatelessSession <code>true</code> to use
|
||||
* {@link StatelessSession} <code>false</code> to use standard hibernate
|
||||
* {@link Session}
|
||||
* @param useStatelessSession <code>true</code> to use {@link StatelessSession}
|
||||
* <code>false</code> to use standard hibernate {@link Session}
|
||||
*/
|
||||
public void setUseStatelessSession(boolean useStatelessSession) {
|
||||
helper.setUseStatelessSession(useStatelessSession);
|
||||
@@ -190,7 +178,6 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
|
||||
/**
|
||||
* Update the context and clear the session if stateful.
|
||||
*
|
||||
* @param executionContext the current {@link ExecutionContext}
|
||||
* @throws ItemStreamException if there is a problem
|
||||
*/
|
||||
@@ -201,11 +188,9 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
}
|
||||
|
||||
/**
|
||||
* Wind forward through the result set to the item requested. Also clears
|
||||
* the session every now and then (if stateful) to avoid memory problems.
|
||||
* The frequency of session clearing is the larger of the fetch size (if
|
||||
* set) and 100.
|
||||
*
|
||||
* Wind forward through the result set to the item requested. Also clears the session
|
||||
* every now and then (if stateful) to avoid memory problems. The frequency of session
|
||||
* clearing is the larger of the fetch size (if set) and 100.
|
||||
* @param itemIndex the first item to read
|
||||
* @throws Exception if there is a problem
|
||||
* @see AbstractItemCountingItemStreamItemReader#jumpToItem(int)
|
||||
@@ -222,7 +207,7 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
@Override
|
||||
protected void doClose() throws Exception {
|
||||
|
||||
if(initialized) {
|
||||
if (initialized) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
@@ -232,4 +217,5 @@ public class HibernateCursorItemReader<T> extends AbstractItemCountingItemStream
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Internal shared state helper for hibernate readers managing sessions and
|
||||
* queries.
|
||||
* Internal shared state helper for hibernate readers managing sessions and queries.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
@@ -78,14 +77,12 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Can be set only in uninitialized state.
|
||||
*
|
||||
* @param useStatelessSession <code>true</code> to use
|
||||
* {@link StatelessSession} <code>false</code> to use standard hibernate
|
||||
* {@link Session}
|
||||
* @param useStatelessSession <code>true</code> to use {@link StatelessSession}
|
||||
* <code>false</code> to use standard hibernate {@link Session}
|
||||
*/
|
||||
public void setUseStatelessSession(boolean useStatelessSession) {
|
||||
Assert.state(statefulSession == null && statelessSession == null,
|
||||
"The useStatelessSession flag can only be set before a session is initialized.");
|
||||
"The useStatelessSession flag can only be set before a session is initialized.");
|
||||
this.useStatelessSession = useStatelessSession;
|
||||
}
|
||||
|
||||
@@ -104,16 +101,14 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
|
||||
if (queryProvider == null) {
|
||||
Assert.notNull(sessionFactory, "session factory must be set");
|
||||
Assert.state(StringUtils.hasText(queryString) ^ StringUtils.hasText(queryName),
|
||||
"queryString or queryName must be set");
|
||||
"queryString or queryName must be set");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cursor over all of the results, with the forward-only flag set.
|
||||
*
|
||||
* @param fetchSize the fetch size to use retrieving the results
|
||||
* @param parameterValues the parameter values to use (or null if none).
|
||||
*
|
||||
* @return a forward-only {@link ScrollableResults}
|
||||
*/
|
||||
public ScrollableResults getForwardOnlyCursor(int fetchSize, Map<String, Object> parameterValues) {
|
||||
@@ -126,7 +121,6 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Open appropriate type of hibernate session and create the query.
|
||||
*
|
||||
* @return a Hibernate Query
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // Hibernate APIs do not use a typed Query
|
||||
@@ -172,7 +166,6 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Scroll through the results up to the item specified.
|
||||
*
|
||||
* @param cursor the results to scroll over
|
||||
* @param itemIndex index to scroll to
|
||||
* @param flushInterval the number of items to scroll past before flushing
|
||||
@@ -201,17 +194,16 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a page of data, clearing the existing session (if necessary) first,
|
||||
* and creating a new session before executing the query.
|
||||
*
|
||||
* Read a page of data, clearing the existing session (if necessary) first, and
|
||||
* creating a new session before executing the query.
|
||||
* @param page the page to read (starting at 0)
|
||||
* @param pageSize the size of the page or maximum number of items to read
|
||||
* @param fetchSize the fetch size to use
|
||||
* @param parameterValues the parameter values to use (if any, otherwise
|
||||
* null)
|
||||
* @param parameterValues the parameter values to use (if any, otherwise null)
|
||||
* @return a collection of items
|
||||
*/
|
||||
public Collection<? extends T> readPage(int page, int pageSize, int fetchSize, Map<String, Object> parameterValues) {
|
||||
public Collection<? extends T> readPage(int page, int pageSize, int fetchSize,
|
||||
Map<String, Object> parameterValues) {
|
||||
|
||||
clear();
|
||||
|
||||
|
||||
@@ -28,16 +28,15 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ItemWriter} that uses a Hibernate session to save or update entities
|
||||
* that are not part of the current Hibernate session. It will also flush the
|
||||
* session after writing (i.e. at chunk boundaries if used in a Spring Batch
|
||||
* TaskletStep). It will also clear the session on write
|
||||
* default (see {@link #setClearSession(boolean) clearSession} property).<br>
|
||||
* {@link ItemWriter} that uses a Hibernate session to save or update entities that are
|
||||
* not part of the current Hibernate session. It will also flush the session after writing
|
||||
* (i.e. at chunk boundaries if used in a Spring Batch TaskletStep). It will also clear
|
||||
* the session on write default (see {@link #setClearSession(boolean) clearSession}
|
||||
* property).<br>
|
||||
* <br>
|
||||
*
|
||||
* The writer is thread-safe once properties are set (normal singleton behavior)
|
||||
* if a {@link CurrentSessionContext} that uses only one session per thread is
|
||||
* used.
|
||||
* The writer is thread-safe once properties are set (normal singleton behavior) if a
|
||||
* {@link CurrentSessionContext} that uses only one session per thread is used.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Thomas Risberg
|
||||
@@ -47,19 +46,16 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(HibernateItemWriter.class);
|
||||
protected static final Log logger = LogFactory.getLog(HibernateItemWriter.class);
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
private boolean clearSession = true;
|
||||
|
||||
/**
|
||||
* Flag to indicate that the session should be cleared and flushed at the
|
||||
* end of the write (default true).
|
||||
*
|
||||
* @param clearSession
|
||||
* the flag value to set
|
||||
* Flag to indicate that the session should be cleared and flushed at the end of the
|
||||
* write (default true).
|
||||
* @param clearSession the flag value to set
|
||||
*/
|
||||
public void setClearSession(boolean clearSession) {
|
||||
this.clearSession = clearSession;
|
||||
@@ -67,7 +63,6 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory to be used internally.
|
||||
*
|
||||
* @param sessionFactory session factory to be used by the writer
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
@@ -79,13 +74,12 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.state(sessionFactory != null,
|
||||
"SessionFactory must be provided");
|
||||
Assert.state(sessionFactory != null, "SessionFactory must be provided");
|
||||
}
|
||||
|
||||
/**
|
||||
* Save or update any entities not in the current hibernate session and then
|
||||
* flush the hibernate session.
|
||||
* Save or update any entities not in the current hibernate session and then flush the
|
||||
* hibernate session.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#write(java.util.List)
|
||||
*/
|
||||
@@ -93,22 +87,20 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
public void write(List<? extends T> items) {
|
||||
doWrite(sessionFactory, items);
|
||||
sessionFactory.getCurrentSession().flush();
|
||||
if(clearSession) {
|
||||
if (clearSession) {
|
||||
sessionFactory.getCurrentSession().clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do perform the actual write operation using Hibernate's API.
|
||||
* This can be overridden in a subclass if necessary.
|
||||
*
|
||||
* Do perform the actual write operation using Hibernate's API. This can be overridden
|
||||
* in a subclass if necessary.
|
||||
* @param sessionFactory Hibernate SessionFactory to be used
|
||||
* @param items the list of items to use for the write
|
||||
*/
|
||||
protected void doWrite(SessionFactory sessionFactory, List<? extends T> items) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing to Hibernate with " + items.size()
|
||||
+ " items.");
|
||||
logger.debug("Writing to Hibernate with " + items.size() + " items.");
|
||||
}
|
||||
|
||||
Session currentSession = sessionFactory.getCurrentSession();
|
||||
@@ -123,8 +115,7 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(saveOrUpdateCount + " entities saved/updated.");
|
||||
logger.debug((items.size() - saveOrUpdateCount)
|
||||
+ " entities found in session.");
|
||||
logger.debug((items.size() - saveOrUpdateCount) + " entities found in session.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,36 +29,31 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ItemReader} for reading database records built on top of Hibernate and
|
||||
* reading only up to a fixed number of items at a time. It executes an HQL
|
||||
* query when initialized is paged as the {@link #read()} method is called. The
|
||||
* query can be set directly using {@link #setQueryString(String)}, a named
|
||||
* query can be used by {@link #setQueryName(String)}, or a query provider
|
||||
* strategy can be supplied via
|
||||
* {@link ItemReader} for reading database records built on top of Hibernate and reading
|
||||
* only up to a fixed number of items at a time. It executes an HQL query when initialized
|
||||
* is paged as the {@link #read()} method is called. The query can be set directly using
|
||||
* {@link #setQueryString(String)}, a named query can be used by
|
||||
* {@link #setQueryName(String)}, or a query provider strategy can be supplied via
|
||||
* {@link #setQueryProvider(HibernateQueryProvider)}.
|
||||
*
|
||||
* <p>
|
||||
* The reader can be configured to use either {@link StatelessSession}
|
||||
* sufficient for simple mappings without the need to cascade to associated
|
||||
* objects or standard hibernate {@link Session} for more advanced mappings or
|
||||
* when caching is desired. When stateful session is used it will be cleared in
|
||||
* the {@link #update(ExecutionContext)} method without being flushed (no data
|
||||
* modifications are expected).
|
||||
* The reader can be configured to use either {@link StatelessSession} sufficient for
|
||||
* simple mappings without the need to cascade to associated objects or standard hibernate
|
||||
* {@link Session} for more advanced mappings or when caching is desired. When stateful
|
||||
* session is used it will be cleared in the {@link #update(ExecutionContext)} method
|
||||
* without being flushed (no data modifications are expected).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The implementation is thread-safe in between calls to
|
||||
* {@link #open(ExecutionContext)}, but remember to use
|
||||
* <code>saveState=false</code> if used in a multi-threaded client (no restart
|
||||
* available).
|
||||
* The implementation is thread-safe in between calls to {@link #open(ExecutionContext)},
|
||||
* but remember to use <code>saveState=false</code> if used in a multi-threaded client (no
|
||||
* restart available).
|
||||
* </p>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
implements InitializingBean {
|
||||
public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T> implements InitializingBean {
|
||||
|
||||
private HibernateItemReaderHelper<T> helper = new HibernateItemReaderHelper<>();
|
||||
|
||||
@@ -72,7 +67,6 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
|
||||
/**
|
||||
* The parameter values to apply to a query (map of name:value).
|
||||
*
|
||||
* @param parameterValues the parameter values to set
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
@@ -82,9 +76,7 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
/**
|
||||
* A query name for an externalized query. Either this or the {
|
||||
* {@link #setQueryString(String) query string} or the {
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} should
|
||||
* be set.
|
||||
*
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} should be set.
|
||||
* @param queryName name of a hibernate named query
|
||||
*/
|
||||
public void setQueryName(String queryName) {
|
||||
@@ -92,9 +84,8 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched
|
||||
* from database per round trip.
|
||||
*
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched from
|
||||
* database per round trip.
|
||||
* @param fetchSize the fetch size to pass down to Hibernate
|
||||
*/
|
||||
public void setFetchSize(int fetchSize) {
|
||||
@@ -102,10 +93,8 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. Either this or the {{@link #setQueryString(String)
|
||||
* query string} or the {{@link #setQueryName(String) query name} should be
|
||||
* set.
|
||||
*
|
||||
* A query provider. Either this or the {{@link #setQueryString(String) query string}
|
||||
* or the {{@link #setQueryName(String) query name} should be set.
|
||||
* @param queryProvider Hibernate query provider
|
||||
*/
|
||||
public void setQueryProvider(HibernateQueryProvider<? extends T> queryProvider) {
|
||||
@@ -116,7 +105,6 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
* A query string in HQL. Either this or the {
|
||||
* {@link #setQueryProvider(HibernateQueryProvider) query provider} or the {
|
||||
* {@link #setQueryName(String) query name} should be set.
|
||||
*
|
||||
* @param queryString HQL query string
|
||||
*/
|
||||
public void setQueryString(String queryString) {
|
||||
@@ -125,7 +113,6 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
|
||||
/**
|
||||
* The Hibernate SessionFactory to use the create a session.
|
||||
*
|
||||
* @param sessionFactory the {@link SessionFactory} to set
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
@@ -134,10 +121,8 @@ public class HibernatePagingItemReader<T> extends AbstractPagingItemReader<T>
|
||||
|
||||
/**
|
||||
* Can be set only in uninitialized state.
|
||||
*
|
||||
* @param useStatelessSession <code>true</code> to use
|
||||
* {@link StatelessSession} <code>false</code> to use standard hibernate
|
||||
* {@link Session}
|
||||
* @param useStatelessSession <code>true</code> to use {@link StatelessSession}
|
||||
* <code>false</code> to use standard hibernate {@link Session}
|
||||
*/
|
||||
public void setUseStatelessSession(boolean useStatelessSession) {
|
||||
helper.setUseStatelessSession(useStatelessSession);
|
||||
|
||||
@@ -23,18 +23,19 @@ import org.springframework.jdbc.core.RowMapper;
|
||||
/**
|
||||
* A convenient strategy for SQL updates, acting effectively as the inverse of
|
||||
* {@link RowMapper}.
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface ItemPreparedStatementSetter<T> {
|
||||
|
||||
/**
|
||||
* Set parameter values on the given PreparedStatement as determined from
|
||||
* the provided item.
|
||||
* Set parameter values on the given PreparedStatement as determined from the provided
|
||||
* item.
|
||||
* @param item the item to obtain the values from
|
||||
* @param ps the PreparedStatement to invoke setter methods on
|
||||
* @throws SQLException if a SQLException is encountered (i.e. there is no
|
||||
* need to catch SQLException)
|
||||
* @throws SQLException if a SQLException is encountered (i.e. there is no need to
|
||||
* catch SQLException)
|
||||
*/
|
||||
void setValues(T item, PreparedStatement ps) throws SQLException;
|
||||
|
||||
|
||||
@@ -19,15 +19,15 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
|
||||
/**
|
||||
* A convenient strategy for providing SqlParameterSource for named parameter SQL updates.
|
||||
*
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ItemSqlParameterSourceProvider<T> {
|
||||
|
||||
/**
|
||||
* Provide parameter values in an {@link SqlParameterSource} based on values from
|
||||
* the provided item.
|
||||
* Provide parameter values in an {@link SqlParameterSource} based on values from the
|
||||
* provided item.
|
||||
* @param item the item to use for parameter values
|
||||
* @return parameters extracted from the item
|
||||
*/
|
||||
|
||||
@@ -37,22 +37,24 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>{@link ItemWriter} that uses the batching features from
|
||||
* <p>
|
||||
* {@link ItemWriter} that uses the batching features from
|
||||
* {@link NamedParameterJdbcTemplate} to execute a batch of statements for all items
|
||||
* provided.</p>
|
||||
* provided.
|
||||
* </p>
|
||||
*
|
||||
* The user must provide an SQL query and a special callback for either of
|
||||
* {@link ItemPreparedStatementSetter} or {@link ItemSqlParameterSourceProvider}.
|
||||
* You can use either named parameters or the traditional '?' placeholders. If you use the
|
||||
* named parameter support then you should provide a {@link ItemSqlParameterSourceProvider},
|
||||
* otherwise you should provide a {@link ItemPreparedStatementSetter}.
|
||||
* This callback would be responsible for mapping the item to the parameters needed to
|
||||
* execute the SQL statement.<br>
|
||||
* {@link ItemPreparedStatementSetter} or {@link ItemSqlParameterSourceProvider}. You can
|
||||
* use either named parameters or the traditional '?' placeholders. If you use the named
|
||||
* parameter support then you should provide a {@link ItemSqlParameterSourceProvider},
|
||||
* otherwise you should provide a {@link ItemPreparedStatementSetter}. This callback would
|
||||
* be responsible for mapping the item to the parameters needed to execute the SQL
|
||||
* statement.<br>
|
||||
*
|
||||
* It is expected that {@link #write(List)} is called inside a transaction.<br>
|
||||
*
|
||||
* The writer is thread-safe after its properties are set (normal singleton
|
||||
* behavior), so it can be used to write in multiple concurrent transactions.
|
||||
* The writer is thread-safe after its properties are set (normal singleton behavior), so
|
||||
* it can be used to write in multiple concurrent transactions.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Thomas Risberg
|
||||
@@ -78,8 +80,8 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
protected boolean usingNamedParameters;
|
||||
|
||||
/**
|
||||
* Public setter for the flag that determines whether an assertion is made
|
||||
* that all items cause at least one row to be updated.
|
||||
* Public setter for the flag that determines whether an assertion is made that all
|
||||
* items cause at least one row to be updated.
|
||||
* @param assertUpdates the flag to set. Defaults to true;
|
||||
*/
|
||||
public void setAssertUpdates(boolean assertUpdates) {
|
||||
@@ -87,9 +89,8 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the query string to execute on write. The parameters
|
||||
* should correspond to those known to the
|
||||
* {@link ItemPreparedStatementSetter}.
|
||||
* Public setter for the query string to execute on write. The parameters should
|
||||
* correspond to those known to the {@link ItemPreparedStatementSetter}.
|
||||
* @param sql the query to set
|
||||
*/
|
||||
public void setSql(String sql) {
|
||||
@@ -98,8 +99,8 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemPreparedStatementSetter}.
|
||||
* @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to
|
||||
* set. This is required when using traditional '?' placeholders for the SQL statement.
|
||||
* @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to set. This
|
||||
* is required when using traditional '?' placeholders for the SQL statement.
|
||||
*/
|
||||
public void setItemPreparedStatementSetter(ItemPreparedStatementSetter<T> preparedStatementSetter) {
|
||||
this.itemPreparedStatementSetter = preparedStatementSetter;
|
||||
@@ -108,8 +109,8 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
/**
|
||||
* Public setter for the {@link ItemSqlParameterSourceProvider}.
|
||||
* @param itemSqlParameterSourceProvider the {@link ItemSqlParameterSourceProvider} to
|
||||
* set. This is required when using named parameters for the SQL statement and the type
|
||||
* to be written does not implement {@link Map}.
|
||||
* set. This is required when using named parameters for the SQL statement and the
|
||||
* type to be written does not implement {@link Map}.
|
||||
*/
|
||||
public void setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) {
|
||||
this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider;
|
||||
@@ -117,7 +118,6 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
|
||||
/**
|
||||
* Public setter for the data source for injection purposes.
|
||||
*
|
||||
* @param dataSource {@link javax.sql.DataSource} to use for querying against
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
@@ -135,8 +135,8 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL statement plus a
|
||||
* parameter source.
|
||||
* Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL
|
||||
* statement plus a parameter source.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
@@ -146,16 +146,20 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql, namedParameters);
|
||||
if (namedParameters.size() > 0) {
|
||||
if (parameterCount != namedParameters.size()) {
|
||||
throw new InvalidDataAccessApiUsageException("You can't use both named parameters and classic \"?\" placeholders: " + sql);
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"You can't use both named parameters and classic \"?\" placeholders: " + sql);
|
||||
}
|
||||
usingNamedParameters = true;
|
||||
}
|
||||
if (!usingNamedParameters) {
|
||||
Assert.notNull(itemPreparedStatementSetter, "Using SQL statement with '?' placeholders requires an ItemPreparedStatementSetter");
|
||||
Assert.notNull(itemPreparedStatementSetter,
|
||||
"Using SQL statement with '?' placeholders requires an ItemPreparedStatementSetter");
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#write(java.util.List)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -171,9 +175,10 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
int[] updateCounts;
|
||||
|
||||
if (usingNamedParameters) {
|
||||
if(items.get(0) instanceof Map && this.itemSqlParameterSourceProvider == null) {
|
||||
if (items.get(0) instanceof Map && this.itemSqlParameterSourceProvider == null) {
|
||||
updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, items.toArray(new Map[items.size()]));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
SqlParameterSource[] batchArgs = new SqlParameterSource[items.size()];
|
||||
int i = 0;
|
||||
for (T item : items) {
|
||||
@@ -183,16 +188,18 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
}
|
||||
else {
|
||||
updateCounts = namedParameterJdbcTemplate.getJdbcOperations().execute(sql, new PreparedStatementCallback<int[]>() {
|
||||
@Override
|
||||
public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
|
||||
for (T item : items) {
|
||||
itemPreparedStatementSetter.setValues(item, ps);
|
||||
ps.addBatch();
|
||||
}
|
||||
return ps.executeBatch();
|
||||
}
|
||||
});
|
||||
updateCounts = namedParameterJdbcTemplate.getJdbcOperations().execute(sql,
|
||||
new PreparedStatementCallback<int[]>() {
|
||||
@Override
|
||||
public int[] doInPreparedStatement(PreparedStatement ps)
|
||||
throws SQLException, DataAccessException {
|
||||
for (T item : items) {
|
||||
itemPreparedStatementSetter.setValues(item, ps);
|
||||
ps.addBatch();
|
||||
}
|
||||
return ps.executeBatch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (assertUpdates) {
|
||||
@@ -206,4 +213,5 @@ public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,15 +30,16 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Simple item reader implementation that opens a JDBC cursor and continually retrieves the
|
||||
* next row in the ResultSet.
|
||||
* Simple item reader implementation that opens a JDBC cursor and continually retrieves
|
||||
* the next row in the ResultSet.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The statement used to open the cursor is created with the 'READ_ONLY' option since a non read-only
|
||||
* cursor may unnecessarily lock tables or rows. It is also opened with 'TYPE_FORWARD_ONLY' option.
|
||||
* By default the cursor will be opened using a separate connection which means that it will not participate
|
||||
* in any transactions created as part of the step processing.
|
||||
* The statement used to open the cursor is created with the 'READ_ONLY' option since a
|
||||
* non read-only cursor may unnecessarily lock tables or rows. It is also opened with
|
||||
* 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened using a separate
|
||||
* connection which means that it will not participate in any transactions created as part
|
||||
* of the step processing.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -69,7 +70,6 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
/**
|
||||
* Set the RowMapper to be used for all calls to read().
|
||||
*
|
||||
* @param rowMapper the mapper used to map each item
|
||||
*/
|
||||
public void setRowMapper(RowMapper<T> rowMapper) {
|
||||
@@ -77,10 +77,9 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL statement to be used when creating the cursor. This statement
|
||||
* should be a complete and valid SQL statement, as it will be run directly
|
||||
* without any modification.
|
||||
*
|
||||
* Set the SQL statement to be used when creating the cursor. This statement should be
|
||||
* a complete and valid SQL statement, as it will be run directly without any
|
||||
* modification.
|
||||
* @param sql SQL statement
|
||||
*/
|
||||
public void setSql(String sql) {
|
||||
@@ -88,10 +87,10 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PreparedStatementSetter to use if any parameter values that need
|
||||
* to be set in the supplied query.
|
||||
*
|
||||
* @param preparedStatementSetter PreparedStatementSetter responsible for filling out the statement
|
||||
* Set the PreparedStatementSetter to use if any parameter values that need to be set
|
||||
* in the supplied query.
|
||||
* @param preparedStatementSetter PreparedStatementSetter responsible for filling out
|
||||
* the statement
|
||||
*/
|
||||
public void setPreparedStatementSetter(PreparedStatementSetter preparedStatementSetter) {
|
||||
this.preparedStatementSetter = preparedStatementSetter;
|
||||
@@ -99,9 +98,7 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
/**
|
||||
* Assert that mandatory properties are set.
|
||||
*
|
||||
* @throws IllegalArgumentException if either data source or SQL properties
|
||||
* not set.
|
||||
* @throws IllegalArgumentException if either data source or SQL properties not set.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -110,7 +107,6 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
Assert.notNull(rowMapper, "RowMapper must be provided");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void openCursor(Connection con) {
|
||||
try {
|
||||
@@ -135,7 +131,6 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected T readCursor(ResultSet rs, int currentRow) throws SQLException {
|
||||
@@ -156,4 +151,5 @@ public class JdbcCursorItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
public String getSql() {
|
||||
return this.sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,35 +40,33 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link org.springframework.batch.item.ItemReader} for reading database
|
||||
* records using JDBC in a paging fashion.
|
||||
* {@link org.springframework.batch.item.ItemReader} for reading database records using
|
||||
* JDBC in a paging fashion.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* It executes the SQL built by the {@link PagingQueryProvider} to retrieve
|
||||
* requested data. The query is executed using paged requests of a size
|
||||
* specified in {@link #setPageSize(int)}. Additional pages are requested when
|
||||
* needed as {@link #read()} method is called, returning an object corresponding
|
||||
* to current position. On restart it uses the last sort key value to locate the
|
||||
* first page to read (so it doesn't matter if the successfully processed items
|
||||
* have been removed or modified). It is important to have a unique key constraint
|
||||
* on the sort key to guarantee that no data is lost between executions.
|
||||
* It executes the SQL built by the {@link PagingQueryProvider} to retrieve requested
|
||||
* data. The query is executed using paged requests of a size specified in
|
||||
* {@link #setPageSize(int)}. Additional pages are requested when needed as
|
||||
* {@link #read()} method is called, returning an object corresponding to current
|
||||
* position. On restart it uses the last sort key value to locate the first page to read
|
||||
* (so it doesn't matter if the successfully processed items have been removed or
|
||||
* modified). It is important to have a unique key constraint on the sort key to guarantee
|
||||
* that no data is lost between executions.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The performance of the paging depends on the database specific features
|
||||
* available to limit the number of returned rows. Setting a fairly large page
|
||||
* size and using a commit interval that matches the page size should provide
|
||||
* better performance.
|
||||
* The performance of the paging depends on the database specific features available to
|
||||
* limit the number of returned rows. Setting a fairly large page size and using a commit
|
||||
* interval that matches the page size should provide better performance.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The implementation is thread-safe in between calls to
|
||||
* {@link #open(ExecutionContext)}, but remember to use
|
||||
* <code>saveState=false</code> if used in a multi-threaded client (no restart
|
||||
* available).
|
||||
* The implementation is thread-safe in between calls to {@link #open(ExecutionContext)},
|
||||
* but remember to use <code>saveState=false</code> if used in a multi-threaded client (no
|
||||
* restart available).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
@@ -76,6 +74,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> implements InitializingBean {
|
||||
|
||||
private static final String START_AFTER_VALUE = "start.after";
|
||||
|
||||
public static final int VALUE_NOT_SET = -1;
|
||||
@@ -95,7 +94,7 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
private String remainingPagesSql;
|
||||
|
||||
private Map<String, Object> startAfterValues;
|
||||
|
||||
|
||||
private Map<String, Object> previousStartAfterValues;
|
||||
|
||||
private int fetchSize = VALUE_NOT_SET;
|
||||
@@ -109,11 +108,9 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be
|
||||
* fetched from the database when more rows are needed for this
|
||||
* <code>ResultSet</code> object. If the fetch size specified is zero, the
|
||||
* JDBC driver ignores the value.
|
||||
*
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be fetched from
|
||||
* the database when more rows are needed for this <code>ResultSet</code> object. If
|
||||
* the fetch size specified is zero, the JDBC driver ignores the value.
|
||||
* @param fetchSize the number of rows to fetch
|
||||
* @see ResultSet#setFetchSize(int)
|
||||
*/
|
||||
@@ -122,9 +119,8 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link PagingQueryProvider}. Supplies all the platform dependent query
|
||||
* generation capabilities needed by the reader.
|
||||
*
|
||||
* A {@link PagingQueryProvider}. Supplies all the platform dependent query generation
|
||||
* capabilities needed by the reader.
|
||||
* @param queryProvider the {@link PagingQueryProvider} to use
|
||||
*/
|
||||
public void setQueryProvider(PagingQueryProvider queryProvider) {
|
||||
@@ -132,13 +128,9 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
}
|
||||
|
||||
/**
|
||||
* The row mapper implementation to be used by this reader. The row mapper
|
||||
* is used to convert result set rows into objects, which are then returned
|
||||
* by the reader.
|
||||
*
|
||||
* @param rowMapper a
|
||||
* {@link RowMapper}
|
||||
* implementation
|
||||
* The row mapper implementation to be used by this reader. The row mapper is used to
|
||||
* convert result set rows into objects, which are then returned by the reader.
|
||||
* @param rowMapper a {@link RowMapper} implementation
|
||||
*/
|
||||
public void setRowMapper(RowMapper<T> rowMapper) {
|
||||
this.rowMapper = rowMapper;
|
||||
@@ -146,13 +138,11 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
|
||||
/**
|
||||
* The parameter values to be used for the query execution. If you use named
|
||||
* parameters then the key should be the name used in the query clause. If
|
||||
* you use "?" placeholders then the key should be the relative index that
|
||||
* the parameter appears in the query string built using the select, from
|
||||
* and where clauses specified.
|
||||
*
|
||||
* @param parameterValues the values keyed by the parameter named/index used
|
||||
* in the query string.
|
||||
* parameters then the key should be the name used in the query clause. If you use "?"
|
||||
* placeholders then the key should be the relative index that the parameter appears
|
||||
* in the query string built using the select, from and where clauses specified.
|
||||
* @param parameterValues the values keyed by the parameter named/index used in the
|
||||
* query string.
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
this.parameterValues = parameterValues;
|
||||
@@ -197,8 +187,8 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
}
|
||||
if (parameterValues != null && parameterValues.size() > 0) {
|
||||
if (this.queryProvider.isUsingNamedParameters()) {
|
||||
query = namedParameterJdbcTemplate.query(firstPageSql,
|
||||
getParameterMap(parameterValues, null), rowCallback);
|
||||
query = namedParameterJdbcTemplate.query(firstPageSql, getParameterMap(parameterValues, null),
|
||||
rowCallback);
|
||||
}
|
||||
else {
|
||||
query = getJdbcTemplate().query(firstPageSql, rowCallback,
|
||||
@@ -237,14 +227,15 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
if (isSaveState()) {
|
||||
if (isAtEndOfPage() && startAfterValues != null) {
|
||||
// restart on next page
|
||||
executionContext.put(getExecutionContextKey(START_AFTER_VALUE), startAfterValues);
|
||||
} else if (previousStartAfterValues != null) {
|
||||
executionContext.put(getExecutionContextKey(START_AFTER_VALUE), startAfterValues);
|
||||
}
|
||||
else if (previousStartAfterValues != null) {
|
||||
// restart on current page
|
||||
executionContext.put(getExecutionContextKey(START_AFTER_VALUE), previousStartAfterValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isAtEndOfPage() {
|
||||
return getCurrentItemCount() % getPageSize() == 0;
|
||||
}
|
||||
@@ -255,7 +246,7 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
if (isSaveState()) {
|
||||
startAfterValues = (Map<String, Object>) executionContext.get(getExecutionContextKey(START_AFTER_VALUE));
|
||||
|
||||
if(startAfterValues == null) {
|
||||
if (startAfterValues == null) {
|
||||
startAfterValues = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -266,10 +257,11 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
@Override
|
||||
protected void doJumpToPage(int itemIndex) {
|
||||
/*
|
||||
* Normally this would be false (the startAfterValue is enough
|
||||
* information to restart from.
|
||||
* Normally this would be false (the startAfterValue is enough information to
|
||||
* restart from.
|
||||
*/
|
||||
// TODO: this is dead code, startAfterValues is never null - see #open(ExecutionContext)
|
||||
// TODO: this is dead code, startAfterValues is never null - see
|
||||
// #open(ExecutionContext)
|
||||
if (startAfterValues == null && getPage() > 0) {
|
||||
|
||||
String jumpToItemSql = queryProvider.generateJumpToItemQuery(itemIndex, getPageSize());
|
||||
@@ -277,12 +269,14 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SQL used for jumping: [" + jumpToItemSql + "]");
|
||||
}
|
||||
|
||||
|
||||
if (this.queryProvider.isUsingNamedParameters()) {
|
||||
startAfterValues = namedParameterJdbcTemplate.queryForMap(jumpToItemSql, getParameterMap(parameterValues, null));
|
||||
startAfterValues = namedParameterJdbcTemplate.queryForMap(jumpToItemSql,
|
||||
getParameterMap(parameterValues, null));
|
||||
}
|
||||
else {
|
||||
startAfterValues = getJdbcTemplate().queryForMap(jumpToItemSql, getParameterList(parameterValues, null).toArray());
|
||||
startAfterValues = getJdbcTemplate().queryForMap(jumpToItemSql,
|
||||
getParameterList(parameterValues, null).toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,8 +307,8 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
if (sortKeyValue != null && sortKeyValue.size() > 0) {
|
||||
List<Map.Entry<String, Object>> keys = new ArrayList<>(sortKeyValue.entrySet());
|
||||
|
||||
for(int i = 0; i < keys.size(); i++) {
|
||||
for(int j = 0; j < i; j++) {
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
parameterList.add(keys.get(j).getValue());
|
||||
}
|
||||
|
||||
@@ -329,6 +323,7 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
}
|
||||
|
||||
private class PagingRowMapper implements RowMapper<T> {
|
||||
|
||||
@Override
|
||||
public T mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
startAfterValues = new LinkedHashMap<>();
|
||||
@@ -338,9 +333,11 @@ public class JdbcPagingItemReader<T> extends AbstractPagingItemReader<T> impleme
|
||||
|
||||
return rowMapper.mapRow(rs, rowNum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private JdbcTemplate getJdbcTemplate() {
|
||||
return (JdbcTemplate) namedParameterJdbcTemplate.getJdbcOperations();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,22 +34,21 @@ public class JdbcParameterUtils {
|
||||
|
||||
/**
|
||||
* Count the occurrences of the character placeholder in an SQL string
|
||||
* <code>sql</code>. The character placeholder is not counted if it appears
|
||||
* within a literal, that is, surrounded by single or double quotes. This method will
|
||||
* count traditional placeholders in the form of a question mark ('?') as well as
|
||||
* named parameters indicated with a leading ':' or '&'.
|
||||
* <code>sql</code>. The character placeholder is not counted if it appears within a
|
||||
* literal, that is, surrounded by single or double quotes. This method will count
|
||||
* traditional placeholders in the form of a question mark ('?') as well as named
|
||||
* parameters indicated with a leading ':' or '&'.
|
||||
*
|
||||
* The code for this method is taken from an early version of the
|
||||
* {@link org.springframework.jdbc.core.namedparam.NamedParameterUtils}
|
||||
* class. That method was later removed after some refactoring, but the code
|
||||
* is useful here for the Spring Batch project. The code has been altered to better
|
||||
* suite the batch processing requirements.
|
||||
*
|
||||
* {@link org.springframework.jdbc.core.namedparam.NamedParameterUtils} class. That
|
||||
* method was later removed after some refactoring, but the code is useful here for
|
||||
* the Spring Batch project. The code has been altered to better suite the batch
|
||||
* processing requirements.
|
||||
* @param sql String to search in. Returns 0 if the given String is <code>null</code>.
|
||||
* @param namedParameterHolder holder for the named parameters
|
||||
* @return the number of named parameter placeholders
|
||||
*/
|
||||
public static int countParameterPlaceholders(String sql, List<String> namedParameterHolder ) {
|
||||
public static int countParameterPlaceholders(String sql, List<String> namedParameterHolder) {
|
||||
if (sql == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -103,16 +102,15 @@ public class JdbcParameterUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a parameter name continues at the current position,
|
||||
* that is, does not end delimited by any whitespace character yet.
|
||||
* Determine whether a parameter name continues at the current position, that is, does
|
||||
* not end delimited by any whitespace character yet.
|
||||
* @param statement the SQL statement
|
||||
* @param pos the position within the statement
|
||||
*/
|
||||
private static boolean parameterNameContinues(String statement, int pos) {
|
||||
char character = statement.charAt(pos);
|
||||
return (character != ' ' && character != ',' && character != ')' &&
|
||||
character != '"' && character != '\'' && character != '|' &&
|
||||
character != ';' && character != '\n' && character != '\r');
|
||||
return (character != ' ' && character != ',' && character != ')' && character != '"' && character != '\''
|
||||
&& character != '|' && character != ';' && character != '\n' && character != '\r');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,27 +32,31 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.ItemStreamReader} implementation based
|
||||
* on JPA {@link Query#getResultStream()}. It executes the JPQL query when
|
||||
* initialized and iterates over the result set as {@link #read()} method is called,
|
||||
* returning an object corresponding to the current row. The query can be set
|
||||
* directly using {@link #setQueryString(String)}, or using a query provider via
|
||||
* {@link #setQueryProvider(JpaQueryProvider)}.
|
||||
*
|
||||
* {@link org.springframework.batch.item.ItemStreamReader} implementation based on JPA
|
||||
* {@link Query#getResultStream()}. It executes the JPQL query when initialized and
|
||||
* iterates over the result set as {@link #read()} method is called, returning an object
|
||||
* corresponding to the current row. The query can be set directly using
|
||||
* {@link #setQueryString(String)}, or using a query provider via
|
||||
* {@link #setQueryProvider(JpaQueryProvider)}.
|
||||
*
|
||||
* The implementation is <b>not</b> thread-safe.
|
||||
*
|
||||
*
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @param <T> type of items to read
|
||||
* @since 4.3
|
||||
*/
|
||||
public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemReader<T>
|
||||
implements InitializingBean {
|
||||
public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> implements InitializingBean {
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private JpaQueryProvider queryProvider;
|
||||
|
||||
private Map<String, Object> parameterValues;
|
||||
|
||||
private Iterator<T> iterator;
|
||||
|
||||
/**
|
||||
@@ -64,7 +68,6 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
|
||||
|
||||
/**
|
||||
* Set the JPA entity manager factory.
|
||||
*
|
||||
* @param entityManagerFactory JPA entity manager factory
|
||||
*/
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
@@ -73,7 +76,6 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
|
||||
|
||||
/**
|
||||
* Set the JPA query provider.
|
||||
*
|
||||
* @param queryProvider JPA query provider
|
||||
*/
|
||||
public void setQueryProvider(JpaQueryProvider queryProvider) {
|
||||
@@ -82,7 +84,6 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
|
||||
|
||||
/**
|
||||
* Set the JPQL query string.
|
||||
*
|
||||
* @param queryString JPQL query string
|
||||
*/
|
||||
public void setQueryString(String queryString) {
|
||||
@@ -91,9 +92,8 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
|
||||
|
||||
/**
|
||||
* Set the parameter values to be used for the query execution.
|
||||
*
|
||||
* @param parameterValues the values keyed by parameter names used in
|
||||
* the query string.
|
||||
* @param parameterValues the values keyed by parameter names used in the query
|
||||
* string.
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
this.parameterValues = parameterValues;
|
||||
@@ -150,4 +150,5 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
|
||||
this.entityManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,17 +30,15 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.ItemWriter} that is using a JPA
|
||||
* EntityManagerFactory to merge any Entities that aren't part of the
|
||||
* persistence context.
|
||||
* EntityManagerFactory to merge any Entities that aren't part of the persistence context.
|
||||
*
|
||||
* It is required that {@link #write(List)} is called inside a transaction.<br>
|
||||
*
|
||||
* The reader must be configured with an
|
||||
* {@link jakarta.persistence.EntityManagerFactory} that is capable of
|
||||
* participating in Spring managed transactions.
|
||||
* The reader must be configured with an {@link jakarta.persistence.EntityManagerFactory}
|
||||
* that is capable of participating in Spring managed transactions.
|
||||
*
|
||||
* The writer is thread-safe after its properties are set (normal singleton
|
||||
* behaviour), so it can be used to write in multiple concurrent transactions.
|
||||
* The writer is thread-safe after its properties are set (normal singleton behaviour), so
|
||||
* it can be used to write in multiple concurrent transactions.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Mahmoud Ben Hassine
|
||||
@@ -51,20 +49,19 @@ public class JpaItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
protected static final Log logger = LogFactory.getLog(JpaItemWriter.class);
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
private boolean usePersist = false;
|
||||
|
||||
/**
|
||||
* Set the EntityManager to be used internally.
|
||||
*
|
||||
* @param entityManagerFactory the entityManagerFactory to set
|
||||
*/
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether the EntityManager should perform a persist instead of a merge.
|
||||
*
|
||||
* @param usePersist whether to use persist instead of merge.
|
||||
*/
|
||||
public void setUsePersist(boolean usePersist) {
|
||||
@@ -80,8 +77,8 @@ public class JpaItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge all provided items that aren't already in the persistence context
|
||||
* and then flush the entity manager.
|
||||
* Merge all provided items that aren't already in the persistence context and then
|
||||
* flush the entity manager.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#write(java.util.List)
|
||||
*/
|
||||
@@ -96,9 +93,8 @@ public class JpaItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Do perform the actual write operation. This can be overridden in a
|
||||
* subclass if necessary.
|
||||
*
|
||||
* Do perform the actual write operation. This can be overridden in a subclass if
|
||||
* necessary.
|
||||
* @param entityManager the EntityManager to use for the operation
|
||||
* @param items the list of items to use for the write
|
||||
*/
|
||||
@@ -112,12 +108,12 @@ public class JpaItemWriter<T> implements ItemWriter<T>, InitializingBean {
|
||||
long addedToContextCount = 0;
|
||||
for (T item : items) {
|
||||
if (!entityManager.contains(item)) {
|
||||
if(usePersist) {
|
||||
if (usePersist) {
|
||||
entityManager.persist(item);
|
||||
}
|
||||
else {
|
||||
entityManager.merge(item);
|
||||
}
|
||||
}
|
||||
addedToContextCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,50 +34,47 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link org.springframework.batch.item.ItemReader} for reading database
|
||||
* records built on top of JPA.
|
||||
* {@link org.springframework.batch.item.ItemReader} for reading database records built on
|
||||
* top of JPA.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It executes the JPQL {@link #setQueryString(String)} to retrieve requested
|
||||
* data. The query is executed using paged requests of a size specified in
|
||||
* It executes the JPQL {@link #setQueryString(String)} to retrieve requested data. The
|
||||
* query is executed using paged requests of a size specified in
|
||||
* {@link #setPageSize(int)}. Additional pages are requested when needed as
|
||||
* {@link #read()} method is called, returning an object corresponding to
|
||||
* current position.
|
||||
* {@link #read()} method is called, returning an object corresponding to current
|
||||
* position.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The performance of the paging depends on the JPA implementation and its use
|
||||
* of database specific features to limit the number of returned rows.
|
||||
* The performance of the paging depends on the JPA implementation and its use of database
|
||||
* specific features to limit the number of returned rows.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Setting a fairly large page size and using a commit interval that matches the
|
||||
* page size should provide better performance.
|
||||
* Setting a fairly large page size and using a commit interval that matches the page size
|
||||
* should provide better performance.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* In order to reduce the memory usage for large results the persistence context
|
||||
* is flushed and cleared after each page is read. This causes any entities read
|
||||
* to be detached. If you make changes to the entities and want the changes
|
||||
* persisted then you must explicitly merge the entities.
|
||||
* In order to reduce the memory usage for large results the persistence context is
|
||||
* flushed and cleared after each page is read. This causes any entities read to be
|
||||
* detached. If you make changes to the entities and want the changes persisted then you
|
||||
* must explicitly merge the entities.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The reader must be configured with an
|
||||
* {@link jakarta.persistence.EntityManagerFactory}. All entity access is
|
||||
* performed within a new transaction, independent of any existing Spring
|
||||
* managed transactions.
|
||||
* The reader must be configured with an {@link jakarta.persistence.EntityManagerFactory}.
|
||||
* All entity access is performed within a new transaction, independent of any existing
|
||||
* Spring managed transactions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The implementation is thread-safe in between calls to
|
||||
* {@link #open(ExecutionContext)}, but remember to use
|
||||
* <code>saveState=false</code> if used in a multi-threaded client (no restart
|
||||
* available).
|
||||
* The implementation is thread-safe in between calls to {@link #open(ExecutionContext)},
|
||||
* but remember to use <code>saveState=false</code> if used in a multi-threaded client (no
|
||||
* restart available).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Dave Syer
|
||||
* @author Will Schipp
|
||||
@@ -97,8 +94,8 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
|
||||
private JpaQueryProvider queryProvider;
|
||||
|
||||
private Map<String, Object> parameterValues;
|
||||
|
||||
private boolean transacted = true;//default value
|
||||
|
||||
private boolean transacted = true;// default value
|
||||
|
||||
public JpaPagingItemReader() {
|
||||
setName(ClassUtils.getShortName(JpaPagingItemReader.class));
|
||||
@@ -123,25 +120,24 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
|
||||
|
||||
/**
|
||||
* The parameter values to be used for the query execution.
|
||||
*
|
||||
* @param parameterValues the values keyed by the parameter named used in
|
||||
* the query string.
|
||||
* @param parameterValues the values keyed by the parameter named used in the query
|
||||
* string.
|
||||
*/
|
||||
public void setParameterValues(Map<String, Object> parameterValues) {
|
||||
this.parameterValues = parameterValues;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* By default (true) the EntityTransaction will be started and committed around the read.
|
||||
* Can be overridden (false) in cases where the JPA implementation doesn't support a
|
||||
* particular transaction. (e.g. Hibernate with a JTA transaction). NOTE: may cause
|
||||
* problems in guaranteeing the object consistency in the EntityManagerFactory.
|
||||
*
|
||||
* By default (true) the EntityTransaction will be started and committed around the
|
||||
* read. Can be overridden (false) in cases where the JPA implementation doesn't
|
||||
* support a particular transaction. (e.g. Hibernate with a JTA transaction). NOTE:
|
||||
* may cause problems in guaranteeing the object consistency in the
|
||||
* EntityManagerFactory.
|
||||
* @param transacted indicator
|
||||
*/
|
||||
public void setTransacted(boolean transacted) {
|
||||
this.transacted = transacted;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -188,14 +184,14 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
|
||||
protected void doReadPage() {
|
||||
|
||||
EntityTransaction tx = null;
|
||||
|
||||
|
||||
if (transacted) {
|
||||
tx = entityManager.getTransaction();
|
||||
tx.begin();
|
||||
|
||||
|
||||
entityManager.flush();
|
||||
entityManager.clear();
|
||||
}//end if
|
||||
} // end if
|
||||
|
||||
Query query = createQuery().setFirstResult(getPage() * getPageSize()).setMaxResults(getPageSize());
|
||||
|
||||
@@ -211,17 +207,18 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
|
||||
else {
|
||||
results.clear();
|
||||
}
|
||||
|
||||
|
||||
if (!transacted) {
|
||||
List<T> queryResult = query.getResultList();
|
||||
for (T entity : queryResult) {
|
||||
entityManager.detach(entity);
|
||||
results.add(entity);
|
||||
}//end if
|
||||
} else {
|
||||
} // end if
|
||||
}
|
||||
else {
|
||||
results.addAll(query.getResultList());
|
||||
tx.commit();
|
||||
}//end if
|
||||
} // end if
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,9 +17,11 @@ package org.springframework.batch.item.database;
|
||||
|
||||
/**
|
||||
* The direction of the sort in an ORDER BY clause.
|
||||
*
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public enum Order {
|
||||
|
||||
ASCENDING, DESCENDING
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ package org.springframework.batch.item.database;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Interface defining the functionality to be provided for generating paging queries for use with Paging
|
||||
* Item Readers.
|
||||
* Interface defining the functionality to be provided for generating paging queries for
|
||||
* use with Paging Item Readers.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Michael Minella
|
||||
@@ -32,7 +31,6 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* Initialize the query provider using the provided {@link DataSource} if necessary.
|
||||
*
|
||||
* @param dataSource DataSource to use for any initialization
|
||||
* @throws Exception for errors when initializing
|
||||
*/
|
||||
@@ -40,7 +38,6 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* Generate the query that will provide the first page, limited by the page size.
|
||||
*
|
||||
* @param pageSize number of rows to read for each page
|
||||
* @return the generated query
|
||||
*/
|
||||
@@ -48,7 +45,6 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* Generate the query that will provide the first page, limited by the page size.
|
||||
*
|
||||
* @param pageSize number of rows to read for each page
|
||||
* @return the generated query
|
||||
*/
|
||||
@@ -56,10 +52,10 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
*
|
||||
* Generate the query that will provide the jump to item query. The itemIndex provided could be in the middle of
|
||||
* the page and together with the page size it will be used to calculate the last index of the preceding page
|
||||
* to be able to retrieve the sort key for this row.
|
||||
*
|
||||
* Generate the query that will provide the jump to item query. The itemIndex provided
|
||||
* could be in the middle of the page and together with the page size it will be used
|
||||
* to calculate the last index of the preceding page to be able to retrieve the sort
|
||||
* key for this row.
|
||||
* @param itemIndex the index for the next item to be read
|
||||
* @param pageSize number of rows to read for each page
|
||||
* @return the generated query
|
||||
@@ -74,23 +70,20 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* Indicate whether the generated queries use named parameter syntax.
|
||||
*
|
||||
* @return true if named parameter syntax is used
|
||||
*/
|
||||
boolean isUsingNamedParameters();
|
||||
|
||||
/**
|
||||
* The sort keys. A Map of the columns that make up the key and a Boolean indicating ascending or descending
|
||||
* (ascending = true).
|
||||
*
|
||||
* The sort keys. A Map of the columns that make up the key and a Boolean indicating
|
||||
* ascending or descending (ascending = true).
|
||||
* @return the sort keys used to order the query
|
||||
*/
|
||||
Map<String, Order> getSortKeys();
|
||||
|
||||
|
||||
/**
|
||||
* Returns either a String to be used as the named placeholder for a sort key value (based on the column name)
|
||||
* or a ? for unnamed parameters.
|
||||
*
|
||||
* Returns either a String to be used as the named placeholder for a sort key value
|
||||
* (based on the column name) or a ? for unnamed parameters.
|
||||
* @param keyName The sort key name
|
||||
* @return The string to be used for a parameterized query.
|
||||
*/
|
||||
@@ -98,8 +91,8 @@ public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* The sort key (unique single column name) without alias.
|
||||
*
|
||||
* @return the sort key used to order the query (without alias)
|
||||
*/
|
||||
Map<String, Order> getSortKeysWithoutAliases();
|
||||
|
||||
}
|
||||
|
||||
@@ -35,14 +35,15 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Item reader implementation that executes a stored procedure and then reads the returned cursor
|
||||
* and continually retrieves the next row in the <code>ResultSet</code>.
|
||||
* Item reader implementation that executes a stored procedure and then reads the returned
|
||||
* cursor and continually retrieves the next row in the <code>ResultSet</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The callable statement used to open the cursor is created with the 'READ_ONLY' option as well as with the
|
||||
* 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened using a separate connection which means
|
||||
* that it will not participate in any transactions created as part of the step processing.
|
||||
* The callable statement used to open the cursor is created with the 'READ_ONLY' option
|
||||
* as well as with the 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened
|
||||
* using a separate connection which means that it will not participate in any
|
||||
* transactions created as part of the step processing.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -82,7 +83,6 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
/**
|
||||
* Set the RowMapper to be used for all calls to read().
|
||||
*
|
||||
* @param rowMapper the RowMapper to use to map the results
|
||||
*/
|
||||
public void setRowMapper(RowMapper<T> rowMapper) {
|
||||
@@ -90,10 +90,9 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL statement to be used when creating the cursor. This statement
|
||||
* should be a complete and valid SQL statement, as it will be run directly
|
||||
* without any modification.
|
||||
*
|
||||
* Set the SQL statement to be used when creating the cursor. This statement should be
|
||||
* a complete and valid SQL statement, as it will be run directly without any
|
||||
* modification.
|
||||
* @param sprocedureName the SQL used to call the statement
|
||||
*/
|
||||
public void setProcedureName(String sprocedureName) {
|
||||
@@ -101,9 +100,8 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PreparedStatementSetter to use if any parameter values that need
|
||||
* to be set in the supplied query.
|
||||
*
|
||||
* Set the PreparedStatementSetter to use if any parameter values that need to be set
|
||||
* in the supplied query.
|
||||
* @param preparedStatementSetter used to populate the SQL
|
||||
*/
|
||||
public void setPreparedStatementSetter(PreparedStatementSetter preparedStatementSetter) {
|
||||
@@ -111,9 +109,9 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or more declared parameters. Used for configuring this operation when used in a
|
||||
* bean factory. Each parameter will specify SQL type and (optionally) the parameter's name.
|
||||
*
|
||||
* Add one or more declared parameters. Used for configuring this operation when used
|
||||
* in a bean factory. Each parameter will specify SQL type and (optionally) the
|
||||
* parameter's name.
|
||||
* @param parameters Array containing the declared <code>SqlParameter</code> objects
|
||||
*/
|
||||
public void setParameters(SqlParameter[] parameters) {
|
||||
@@ -122,7 +120,6 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
/**
|
||||
* Set whether this stored procedure is a function.
|
||||
*
|
||||
* @param function indicator
|
||||
*/
|
||||
public void setFunction(boolean function) {
|
||||
@@ -130,10 +127,9 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter position of the REF CURSOR. Only used for Oracle and
|
||||
* PostgreSQL that use REF CURSORs. For any other database this should be
|
||||
* kept as 0 which is the default.
|
||||
*
|
||||
* Set the parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL
|
||||
* that use REF CURSORs. For any other database this should be kept as 0 which is the
|
||||
* default.
|
||||
* @param refCursorPosition The parameter position of the REF CURSOR
|
||||
*/
|
||||
public void setRefCursorPosition(int refCursorPosition) {
|
||||
@@ -142,9 +138,7 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
|
||||
/**
|
||||
* Assert that mandatory properties are set.
|
||||
*
|
||||
* @throws IllegalArgumentException if either data source or SQL properties
|
||||
* not set.
|
||||
* @throws IllegalArgumentException if either data source or SQL properties not set.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -157,12 +151,10 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
protected void openCursor(Connection con) {
|
||||
|
||||
Assert.state(procedureName != null, "Procedure Name must not be null.");
|
||||
Assert.state(refCursorPosition >= 0,
|
||||
"invalid refCursorPosition specified as " + refCursorPosition + "; it can't be " +
|
||||
"specified as a negative number.");
|
||||
Assert.state(refCursorPosition == 0 || refCursorPosition > 0,
|
||||
"invalid refCursorPosition specified as " + refCursorPosition + "; there are " +
|
||||
parameters.length + " parameters defined.");
|
||||
Assert.state(refCursorPosition >= 0, "invalid refCursorPosition specified as " + refCursorPosition
|
||||
+ "; it can't be " + "specified as a negative number.");
|
||||
Assert.state(refCursorPosition == 0 || refCursorPosition > 0, "invalid refCursorPosition specified as "
|
||||
+ refCursorPosition + "; there are " + parameters.length + " parameters defined.");
|
||||
|
||||
CallMetaDataContext callContext = new CallMetaDataContext();
|
||||
callContext.setAccessCallParameterMetaData(false);
|
||||
@@ -173,7 +165,6 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
SqlParameter cursorParameter = callContext.createReturnResultSetParameter("cursor", rowMapper);
|
||||
this.callString = callContext.createCallString();
|
||||
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Call string is: " + callString);
|
||||
}
|
||||
@@ -196,7 +187,8 @@ public class StoredProcedureItemReader<T> extends AbstractCursorItemReader<T> {
|
||||
ResultSet.HOLD_CURSORS_OVER_COMMIT);
|
||||
}
|
||||
else {
|
||||
callableStatement = con.prepareCall(callString, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
callableStatement = con.prepareCall(callString, ResultSet.TYPE_FORWARD_ONLY,
|
||||
ResultSet.CONCUR_READ_ONLY);
|
||||
}
|
||||
applyStatementSettings(callableStatement);
|
||||
if (this.preparedStatementSetter != null) {
|
||||
|
||||
@@ -26,13 +26,13 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* This is a builder for the {@link HibernateCursorItemReader}. When configuring, one of
|
||||
* This is a builder for the {@link HibernateCursorItemReader}. When configuring, one of
|
||||
* the following should be provided (listed in order of precedence):
|
||||
* <ul>
|
||||
* <li>{@link #queryProvider(HibernateQueryProvider)}</li>
|
||||
* <li>{@link #queryName(String)}</li>
|
||||
* <li>{@link #queryString(String)}</li>
|
||||
* <li>{@link #nativeQuery(String)} and {@link #entityClass(Class)}</li>
|
||||
* <li>{@link #queryProvider(HibernateQueryProvider)}</li>
|
||||
* <li>{@link #queryName(String)}</li>
|
||||
* <li>{@link #queryString(String)}</li>
|
||||
* <li>{@link #nativeQuery(String)} and {@link #entityClass(Class)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Michael Minella
|
||||
@@ -70,10 +70,9 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -87,7 +86,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -100,7 +98,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -113,7 +110,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -125,9 +121,8 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of parameter values to be set on the query. The key of the map is the name
|
||||
* of the parameter to be set with the value being the value to be set.
|
||||
*
|
||||
* A map of parameter values to be set on the query. The key of the map is the name of
|
||||
* the parameter to be set with the value being the value to be set.
|
||||
* @param parameterValues map of values
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setParameterValues(Map)
|
||||
@@ -140,7 +135,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The name of the Hibernate named query to be executed for this reader.
|
||||
*
|
||||
* @param queryName name of the query to execute
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setQueryName(String)
|
||||
@@ -152,9 +146,8 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of items to be returned with each round trip to the database. Used
|
||||
* The number of items to be returned with each round trip to the database. Used
|
||||
* internally by Hibernate.
|
||||
*
|
||||
* @param fetchSize number of records to return per fetch
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setFetchSize(int)
|
||||
@@ -166,9 +159,8 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. This should be set only if {@link #queryString(String)} and
|
||||
* A query provider. This should be set only if {@link #queryString(String)} and
|
||||
* {@link #queryName(String)} have not been set.
|
||||
*
|
||||
* @param queryProvider the query provider
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setQueryProvider(HibernateQueryProvider)
|
||||
@@ -180,10 +172,9 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* {@link #queryProvider(HibernateQueryProvider)} and {@link #queryName(String)} have
|
||||
* not been set.
|
||||
*
|
||||
* @param queryString the HQL query
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setQueryString(String)
|
||||
@@ -196,7 +187,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The Hibernate {@link SessionFactory} to execute the query against.
|
||||
*
|
||||
* @param sessionFactory the session factory
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setSessionFactory(SessionFactory)
|
||||
@@ -210,7 +200,6 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicator for whether to use a {@link org.hibernate.StatelessSession}
|
||||
* (<code>true</code>) or a {@link org.hibernate.Session} (<code>false</code>).
|
||||
*
|
||||
* @param useStatelessSession Defaults to false
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateCursorItemReader#setUseStatelessSession(boolean)
|
||||
@@ -222,8 +211,7 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to configure a {@link HibernateNativeQueryProvider}. This is ignored if
|
||||
*
|
||||
* Used to configure a {@link HibernateNativeQueryProvider}. This is ignored if
|
||||
* @param nativeQuery {@link String} containing the native query.
|
||||
* @return this instance for method chaining
|
||||
*/
|
||||
@@ -241,16 +229,14 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully constructed {@link HibernateCursorItemReader}.
|
||||
*
|
||||
* @return a new {@link HibernateCursorItemReader}
|
||||
*/
|
||||
public HibernateCursorItemReader<T> build() {
|
||||
Assert.state(this.fetchSize >= 0, "fetchSize must not be negative");
|
||||
Assert.state(this.sessionFactory != null, "A SessionFactory must be provided");
|
||||
|
||||
if(this.saveState) {
|
||||
Assert.state(StringUtils.hasText(this.name),
|
||||
"A name is required when saveState is set to true.");
|
||||
if (this.saveState) {
|
||||
Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true.");
|
||||
}
|
||||
|
||||
HibernateCursorItemReader<T> reader = new HibernateCursorItemReader<>();
|
||||
@@ -258,16 +244,16 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
reader.setFetchSize(this.fetchSize);
|
||||
reader.setParameterValues(this.parameterValues);
|
||||
|
||||
if(this.queryProvider != null) {
|
||||
if (this.queryProvider != null) {
|
||||
reader.setQueryProvider(this.queryProvider);
|
||||
}
|
||||
else if(StringUtils.hasText(this.queryName)) {
|
||||
else if (StringUtils.hasText(this.queryName)) {
|
||||
reader.setQueryName(this.queryName);
|
||||
}
|
||||
else if(StringUtils.hasText(this.queryString)) {
|
||||
else if (StringUtils.hasText(this.queryString)) {
|
||||
reader.setQueryString(this.queryString);
|
||||
}
|
||||
else if(StringUtils.hasText(this.nativeQuery) && this.nativeClass != null) {
|
||||
else if (StringUtils.hasText(this.nativeQuery) && this.nativeClass != null) {
|
||||
HibernateNativeQueryProvider<T> provider = new HibernateNativeQueryProvider<>();
|
||||
provider.setSqlQuery(this.nativeQuery);
|
||||
provider.setEntityClass(this.nativeClass);
|
||||
@@ -282,8 +268,8 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
reader.setQueryProvider(provider);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("A HibernateQueryProvider, queryName, queryString, " +
|
||||
"or both the nativeQuery and entityClass must be configured");
|
||||
throw new IllegalStateException("A HibernateQueryProvider, queryName, queryString, "
|
||||
+ "or both the nativeQuery and entityClass must be configured");
|
||||
}
|
||||
|
||||
reader.setSessionFactory(this.sessionFactory);
|
||||
@@ -296,4 +282,4 @@ public class HibernateCursorItemReaderBuilder<T> {
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public class HibernateItemWriterBuilder<T> {
|
||||
/**
|
||||
* If set to false, the {@link org.hibernate.Session} will not be cleared at the end
|
||||
* of the chunk.
|
||||
*
|
||||
* @param clearSession defaults to true
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateItemWriter#setClearSession(boolean)
|
||||
@@ -48,8 +47,7 @@ public class HibernateItemWriterBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Hibernate {@link SessionFactory} to obtain a session from. Required.
|
||||
*
|
||||
* The Hibernate {@link SessionFactory} to obtain a session from. Required.
|
||||
* @param sessionFactory the {@link SessionFactory}
|
||||
* @return this instance for method chaining
|
||||
* @see HibernateItemWriter#setSessionFactory(SessionFactory)
|
||||
@@ -62,12 +60,10 @@ public class HibernateItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully built {@link HibernateItemWriter}
|
||||
*
|
||||
* @return the writer
|
||||
*/
|
||||
public HibernateItemWriter<T> build() {
|
||||
Assert.state(this.sessionFactory != null,
|
||||
"SessionFactory must be provided");
|
||||
Assert.state(this.sessionFactory != null, "SessionFactory must be provided");
|
||||
|
||||
HibernateItemWriter<T> writer = new HibernateItemWriter<>();
|
||||
writer.setSessionFactory(this.sessionFactory);
|
||||
@@ -75,4 +71,5 @@ public class HibernateItemWriterBuilder<T> {
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A builder for the {@link HibernatePagingItemReader}. When configuring, only one of the
|
||||
* A builder for the {@link HibernatePagingItemReader}. When configuring, only one of the
|
||||
* following should be provided:
|
||||
* <ul>
|
||||
* <li>{@link #queryString(String)}</li>
|
||||
* <li>{@link #queryName(String)}</li>
|
||||
* <li>{@link #queryProvider(HibernateQueryProvider)}</li>
|
||||
* <li>{@link #queryString(String)}</li>
|
||||
* <li>{@link #queryName(String)}</li>
|
||||
* <li>{@link #queryProvider(HibernateQueryProvider)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Michael Minella
|
||||
@@ -66,10 +66,9 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -83,7 +82,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -96,7 +94,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -109,7 +106,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -121,9 +117,8 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* than zero.
|
||||
*
|
||||
* @param pageSize number of items
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setPageSize(int)
|
||||
@@ -135,9 +130,8 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of parameter values to be set on the query. The key of the map is the name
|
||||
* of the parameter to be set with the value being the value to be set.
|
||||
*
|
||||
* A map of parameter values to be set on the query. The key of the map is the name of
|
||||
* the parameter to be set with the value being the value to be set.
|
||||
* @param parameterValues map of values
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setParameterValues(Map)
|
||||
@@ -150,7 +144,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The name of the Hibernate named query to be executed for this reader.
|
||||
*
|
||||
* @param queryName name of the query to execute
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setQueryName(String)
|
||||
@@ -162,9 +155,8 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched
|
||||
* from database per round trip.
|
||||
*
|
||||
* Fetch size used internally by Hibernate to limit amount of data fetched from
|
||||
* database per round trip.
|
||||
* @param fetchSize number of records
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setFetchSize(int)
|
||||
@@ -176,9 +168,8 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. This should be set only if {@link #queryString(String)} and
|
||||
* A query provider. This should be set only if {@link #queryString(String)} and
|
||||
* {@link #queryName(String)} have not been set.
|
||||
*
|
||||
* @param queryProvider the query provider
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setQueryProvider(HibernateQueryProvider)
|
||||
@@ -190,10 +181,9 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* {@link #queryProvider(HibernateQueryProvider)} and {@link #queryName(String)} have
|
||||
* not been set.
|
||||
*
|
||||
* @param queryString the HQL query
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setQueryString(String)
|
||||
@@ -206,7 +196,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The Hibernate {@link SessionFactory} to execute the query against.
|
||||
*
|
||||
* @param sessionFactory the session factory
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setSessionFactory(SessionFactory)
|
||||
@@ -220,7 +209,6 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicator for whether to use a {@link org.hibernate.StatelessSession}
|
||||
* (<code>true</code>) or a {@link org.hibernate.Session} (<code>false</code>).
|
||||
*
|
||||
* @param useStatelessSession Defaults to false
|
||||
* @return this instance for method chaining
|
||||
* @see HibernatePagingItemReader#setUseStatelessSession(boolean)
|
||||
@@ -233,19 +221,17 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully constructed {@link HibernatePagingItemReader}.
|
||||
*
|
||||
* @return a new {@link HibernatePagingItemReader}
|
||||
*/
|
||||
public HibernatePagingItemReader<T> build() {
|
||||
Assert.notNull(this.sessionFactory, "A SessionFactory must be provided");
|
||||
Assert.state(this.fetchSize >= 0, "fetchSize must not be negative");
|
||||
|
||||
if(this.saveState) {
|
||||
Assert.hasText(this.name,
|
||||
"A name is required when saveState is set to true");
|
||||
if (this.saveState) {
|
||||
Assert.hasText(this.name, "A name is required when saveState is set to true");
|
||||
}
|
||||
|
||||
if(this.queryProvider == null) {
|
||||
if (this.queryProvider == null) {
|
||||
Assert.state(StringUtils.hasText(queryString) ^ StringUtils.hasText(queryName),
|
||||
"queryString or queryName must be set");
|
||||
}
|
||||
@@ -267,4 +253,5 @@ public class HibernatePagingItemReaderBuilder<T> {
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the {@link DataSource} to be used.
|
||||
*
|
||||
* @param dataSource the DataSource
|
||||
* @return The current instance of the builder for chaining.
|
||||
* @see JdbcBatchItemWriter#setDataSource(DataSource)
|
||||
@@ -66,8 +65,7 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* If set to true, confirms that every insert results in the update of at least one
|
||||
* row in the database. Defaults to true.
|
||||
*
|
||||
* row in the database. Defaults to true.
|
||||
* @param assertUpdates boolean indicator
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see JdbcBatchItemWriter#setAssertUpdates(boolean)
|
||||
@@ -79,9 +77,7 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL statement to be used for each item's updates. This is a required
|
||||
* field.
|
||||
*
|
||||
* Set the SQL statement to be used for each item's updates. This is a required field.
|
||||
* @param sql SQL string
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see JdbcBatchItemWriter#setSql(String)
|
||||
@@ -93,41 +89,41 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a {@link ItemPreparedStatementSetter} for use by the writer. This
|
||||
* should only be used if {@link #columnMapped()} isn't called.
|
||||
*
|
||||
* Configures a {@link ItemPreparedStatementSetter} for use by the writer. This should
|
||||
* only be used if {@link #columnMapped()} isn't called.
|
||||
* @param itemPreparedStatementSetter The {@link ItemPreparedStatementSetter}
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see JdbcBatchItemWriter#setItemPreparedStatementSetter(ItemPreparedStatementSetter)
|
||||
*/
|
||||
public JdbcBatchItemWriterBuilder<T> itemPreparedStatementSetter(ItemPreparedStatementSetter<T> itemPreparedStatementSetter) {
|
||||
public JdbcBatchItemWriterBuilder<T> itemPreparedStatementSetter(
|
||||
ItemPreparedStatementSetter<T> itemPreparedStatementSetter) {
|
||||
this.itemPreparedStatementSetter = itemPreparedStatementSetter;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a {@link ItemSqlParameterSourceProvider} for use by the writer. This
|
||||
* Configures a {@link ItemSqlParameterSourceProvider} for use by the writer. This
|
||||
* should only be used if {@link #beanMapped()} isn't called.
|
||||
*
|
||||
* @param itemSqlParameterSourceProvider The {@link ItemSqlParameterSourceProvider}
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see JdbcBatchItemWriter#setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider)
|
||||
*/
|
||||
public JdbcBatchItemWriterBuilder<T> itemSqlParameterSourceProvider(ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) {
|
||||
public JdbcBatchItemWriterBuilder<T> itemSqlParameterSourceProvider(
|
||||
ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) {
|
||||
this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link NamedParameterJdbcOperations} instance to use. If one isn't provided,
|
||||
* a {@link DataSource} is required.
|
||||
*
|
||||
* The {@link NamedParameterJdbcOperations} instance to use. If one isn't provided, a
|
||||
* {@link DataSource} is required.
|
||||
* @param namedParameterJdbcOperations The template
|
||||
* @return The current instance of the builder for chaining
|
||||
*/
|
||||
public JdbcBatchItemWriterBuilder<T> namedParametersJdbcTemplate(NamedParameterJdbcOperations namedParameterJdbcOperations) {
|
||||
public JdbcBatchItemWriterBuilder<T> namedParametersJdbcTemplate(
|
||||
NamedParameterJdbcOperations namedParameterJdbcOperations) {
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcOperations;
|
||||
|
||||
return this;
|
||||
@@ -139,7 +135,6 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
*
|
||||
* NOTE: The item type for this {@link org.springframework.batch.item.ItemWriter} must
|
||||
* be castable to <code>Map<String,Object>></code>.
|
||||
*
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see ColumnMapItemPreparedStatementSetter
|
||||
*/
|
||||
@@ -152,7 +147,6 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
/**
|
||||
* Creates a {@link BeanPropertyItemSqlParameterSourceProvider} to be used as your
|
||||
* {@link ItemSqlParameterSourceProvider}.
|
||||
*
|
||||
* @return The current instance of the builder for chaining
|
||||
* @see BeanPropertyItemSqlParameterSourceProvider
|
||||
*/
|
||||
@@ -164,7 +158,6 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates configuration and builds the {@link JdbcBatchItemWriter}.
|
||||
*
|
||||
* @return a {@link JdbcBatchItemWriter}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -174,8 +167,7 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
|
||||
Assert.notNull(this.sql, "A SQL statement is required");
|
||||
int mappedValue = this.mapped.intValue();
|
||||
Assert.state(mappedValue != 3,
|
||||
"Either an item can be mapped via db column or via bean spec, can't be both");
|
||||
Assert.state(mappedValue != 3, "Either an item can be mapped via db column or via bean spec, can't be both");
|
||||
|
||||
JdbcBatchItemWriter<T> writer = new JdbcBatchItemWriter<>();
|
||||
writer.setSql(this.sql);
|
||||
@@ -183,13 +175,15 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
writer.setItemSqlParameterSourceProvider(this.itemSqlParameterSourceProvider);
|
||||
writer.setItemPreparedStatementSetter(this.itemPreparedStatementSetter);
|
||||
|
||||
if(mappedValue == 1) {
|
||||
((JdbcBatchItemWriter<Map<String,Object>>)writer).setItemPreparedStatementSetter(new ColumnMapItemPreparedStatementSetter());
|
||||
} else if(mappedValue == 2) {
|
||||
if (mappedValue == 1) {
|
||||
((JdbcBatchItemWriter<Map<String, Object>>) writer)
|
||||
.setItemPreparedStatementSetter(new ColumnMapItemPreparedStatementSetter());
|
||||
}
|
||||
else if (mappedValue == 2) {
|
||||
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
|
||||
}
|
||||
|
||||
if(this.dataSource != null) {
|
||||
if (this.dataSource != null) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource);
|
||||
}
|
||||
|
||||
@@ -197,4 +191,5 @@ public class JdbcBatchItemWriterBuilder<T> {
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,10 +74,9 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
private boolean connectionAutoCommit;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -91,7 +90,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -104,7 +102,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -117,7 +114,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -130,7 +126,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The {@link DataSource} to read from
|
||||
*
|
||||
* @param dataSource a relational data base
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setDataSource(DataSource)
|
||||
@@ -143,7 +138,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* A hint to the driver as to how many rows to return with each fetch.
|
||||
*
|
||||
* @param fetchSize the hint
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setFetchSize(int)
|
||||
@@ -156,7 +150,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The max number of rows the {@link java.sql.ResultSet} can contain
|
||||
*
|
||||
* @param maxRows the max
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setMaxRows(int)
|
||||
@@ -169,7 +162,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The time in milliseconds for the query to timeout
|
||||
*
|
||||
* @param queryTimeout timeout
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setQueryTimeout(int)
|
||||
@@ -188,9 +180,8 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Indicates if the reader should verify the current position of the
|
||||
* {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults
|
||||
* to true.
|
||||
*
|
||||
* {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults to
|
||||
* true.
|
||||
* @param verifyCursorPosition indicator
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setVerifyCursorPosition(boolean)
|
||||
@@ -204,7 +195,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicates if the JDBC driver supports setting the absolute row on the
|
||||
* {@link java.sql.ResultSet}.
|
||||
*
|
||||
* @param driverSupportsAbsolute indicator
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setDriverSupportsAbsolute(boolean)
|
||||
@@ -218,7 +208,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicates that the connection used for the cursor is being used by all other
|
||||
* processing, therefor part of the same transaction.
|
||||
*
|
||||
* @param useSharedExtendedConnection indicator
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setUseSharedExtendedConnection(boolean)
|
||||
@@ -232,7 +221,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Configures the provided {@link PreparedStatementSetter} to be used to populate any
|
||||
* arguments in the SQL query to be executed for the reader.
|
||||
*
|
||||
* @param preparedStatementSetter setter
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setPreparedStatementSetter(PreparedStatementSetter)
|
||||
@@ -246,7 +234,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Configures a {@link PreparedStatementSetter} that will use the array as the values
|
||||
* to be set on the query to be executed for this reader.
|
||||
*
|
||||
* @param args values to set on the reader query
|
||||
* @return this instance for method chaining
|
||||
*/
|
||||
@@ -258,9 +245,8 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configures a {@link PreparedStatementSetter} that will use the Object [] as the
|
||||
* values to be set on the query to be executed for this reader. The int[] will
|
||||
* values to be set on the query to be executed for this reader. The int[] will
|
||||
* provide the types ({@link java.sql.Types}) for each of the values provided.
|
||||
*
|
||||
* @param args values to set on the query
|
||||
* @param types the type for each value in the args array
|
||||
* @return this instance for method chaining
|
||||
@@ -274,7 +260,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* Configures a {@link PreparedStatementSetter} that will use the List as the values
|
||||
* to be set on the query to be executed for this reader.
|
||||
*
|
||||
* @param args values to set on the query
|
||||
* @return this instance for method chaining
|
||||
*/
|
||||
@@ -287,7 +272,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The query to be executed for this reader
|
||||
*
|
||||
* @param sql query
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setSql(String)
|
||||
@@ -300,7 +284,6 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The {@link RowMapper} used to map the results of the cursor to each item.
|
||||
*
|
||||
* @param rowMapper {@link RowMapper}
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setRowMapper(RowMapper)
|
||||
@@ -312,9 +295,7 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanPropertyRowMapper} to be used as your
|
||||
* {@link RowMapper}.
|
||||
*
|
||||
* Creates a {@link BeanPropertyRowMapper} to be used as your {@link RowMapper}.
|
||||
* @param mappedClass the class for the row mapper
|
||||
* @return this instance for method chaining
|
||||
* @see BeanPropertyRowMapper
|
||||
@@ -326,9 +307,8 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether "autoCommit" should be overridden for the connection used by the cursor.
|
||||
* If not set, defaults to Connection / Datasource default configuration.
|
||||
*
|
||||
* Set whether "autoCommit" should be overridden for the connection used by the
|
||||
* cursor. If not set, defaults to Connection / Datasource default configuration.
|
||||
* @param connectionAutoCommit value to set on underlying JDBC connection
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcCursorItemReader#setConnectionAutoCommit(boolean)
|
||||
@@ -341,13 +321,11 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates configuration and builds a new reader instance.
|
||||
*
|
||||
* @return a fully constructed {@link JdbcCursorItemReader}
|
||||
*/
|
||||
public JdbcCursorItemReader<T> build() {
|
||||
if(this.saveState) {
|
||||
Assert.hasText(this.name,
|
||||
"A name is required when saveState is set to true");
|
||||
if (this.saveState) {
|
||||
Assert.hasText(this.name, "A name is required when saveState is set to true");
|
||||
}
|
||||
|
||||
Assert.hasText(this.sql, "A query is required");
|
||||
@@ -356,7 +334,7 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
JdbcCursorItemReader<T> reader = new JdbcCursorItemReader<>();
|
||||
|
||||
if(StringUtils.hasText(this.name)) {
|
||||
if (StringUtils.hasText(this.name)) {
|
||||
reader.setName(this.name);
|
||||
}
|
||||
|
||||
@@ -378,4 +356,5 @@ public class JdbcCursorItemReaderBuilder<T> {
|
||||
|
||||
return reader;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* This is a builder for the {@link JdbcPagingItemReader}. When configuring, either a
|
||||
* {@link PagingQueryProvider} or the SQL fragments should be provided. If the SQL
|
||||
* This is a builder for the {@link JdbcPagingItemReader}. When configuring, either a
|
||||
* {@link PagingQueryProvider} or the SQL fragments should be provided. If the SQL
|
||||
* fragments are provided, the metadata from the provided {@link DataSource} will be used
|
||||
* to create a PagingQueryProvider for you. If both are provided, the PagingQueryProvider
|
||||
* to create a PagingQueryProvider for you. If both are provided, the PagingQueryProvider
|
||||
* will be used.
|
||||
*
|
||||
* @author Michael Minella
|
||||
@@ -85,10 +85,9 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -102,7 +101,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -115,7 +113,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -128,7 +125,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -140,8 +136,7 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link DataSource} to query against. Required.
|
||||
*
|
||||
* The {@link DataSource} to query against. Required.
|
||||
* @param dataSource the {@link DataSource}
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setDataSource(DataSource)
|
||||
@@ -154,7 +149,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* A hint to the underlying RDBMS as to how many records to return with each fetch.
|
||||
*
|
||||
* @param fetchSize number of records
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setFetchSize(int)
|
||||
@@ -166,8 +160,7 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link RowMapper} used to map the query results to objects. Required.
|
||||
*
|
||||
* The {@link RowMapper} used to map the query results to objects. Required.
|
||||
* @param rowMapper a {@link RowMapper} implementation
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setRowMapper(RowMapper)
|
||||
@@ -179,9 +172,7 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanPropertyRowMapper} to be used as your
|
||||
* {@link RowMapper}.
|
||||
*
|
||||
* Creates a {@link BeanPropertyRowMapper} to be used as your {@link RowMapper}.
|
||||
* @param mappedClass the class for the row mapper
|
||||
* @return this instance for method chaining
|
||||
* @see BeanPropertyRowMapper
|
||||
@@ -194,7 +185,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* A {@link Map} of values to set on the SQL's prepared statement.
|
||||
*
|
||||
* @param parameterValues Map of values
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setParameterValues(Map)
|
||||
@@ -206,9 +196,8 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* than zero.
|
||||
*
|
||||
* @param pageSize number of items
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setPageSize(int)
|
||||
@@ -220,9 +209,9 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The SQL <code>GROUP BY</code> clause for a db specific @{@link PagingQueryProvider}.
|
||||
* This is only used if a PagingQueryProvider is not provided.
|
||||
*
|
||||
* The SQL <code>GROUP BY</code> clause for a db
|
||||
* specific @{@link PagingQueryProvider}. This is only used if a PagingQueryProvider
|
||||
* is not provided.
|
||||
* @param groupClause the SQL clause
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractSqlPagingQueryProvider#setGroupClause(String)
|
||||
@@ -236,7 +225,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
/**
|
||||
* The SQL <code>SELECT</code> clause for a db specific {@link PagingQueryProvider}.
|
||||
* This is only used if a PagingQueryProvider is not provided.
|
||||
*
|
||||
* @param selectClause the SQL clause
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractSqlPagingQueryProvider#setSelectClause(String)
|
||||
@@ -250,7 +238,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
/**
|
||||
* The SQL <code>FROM</code> clause for a db specific {@link PagingQueryProvider}.
|
||||
* This is only used if a PagingQueryProvider is not provided.
|
||||
*
|
||||
* @param fromClause the SQL clause
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractSqlPagingQueryProvider#setFromClause(String)
|
||||
@@ -264,7 +251,6 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
/**
|
||||
* The SQL <code>WHERE</code> clause for a db specific {@link PagingQueryProvider}.
|
||||
* This is only used if a PagingQueryProvider is not provided.
|
||||
*
|
||||
* @param whereClause the SQL clause
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractSqlPagingQueryProvider#setWhereClause(String)
|
||||
@@ -276,8 +262,7 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The keys to sort by. These keys <em>must</em> create a unique key.
|
||||
*
|
||||
* The keys to sort by. These keys <em>must</em> create a unique key.
|
||||
* @param sortKeys keys to sort by and the direction for each.
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractSqlPagingQueryProvider#setSortKeys(Map)
|
||||
@@ -289,11 +274,10 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link PagingQueryProvider} to provide the queries required. If provided, the
|
||||
* SQL fragments configured via {@link #selectClause(String)},
|
||||
* A {@link PagingQueryProvider} to provide the queries required. If provided, the SQL
|
||||
* fragments configured via {@link #selectClause(String)},
|
||||
* {@link #fromClause(String)}, {@link #whereClause(String)}, {@link #groupClause},
|
||||
* and {@link #sortKeys(Map)} are ignored.
|
||||
*
|
||||
* @param provider the db specific query provider
|
||||
* @return this instance for method chaining
|
||||
* @see JdbcPagingItemReader#setQueryProvider(PagingQueryProvider)
|
||||
@@ -306,16 +290,14 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Provides a completely built instance of the {@link JdbcPagingItemReader}
|
||||
*
|
||||
* @return a {@link JdbcPagingItemReader}
|
||||
*/
|
||||
public JdbcPagingItemReader<T> build() {
|
||||
Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero");
|
||||
Assert.notNull(this.dataSource, "dataSource is required");
|
||||
|
||||
if(this.saveState) {
|
||||
Assert.hasText(this.name,
|
||||
"A name is required when saveState is set to true");
|
||||
if (this.saveState) {
|
||||
Assert.hasText(this.name, "A name is required when saveState is set to true");
|
||||
}
|
||||
|
||||
JdbcPagingItemReader<T> reader = new JdbcPagingItemReader<>();
|
||||
@@ -328,7 +310,7 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
reader.setFetchSize(this.fetchSize);
|
||||
reader.setParameterValues(this.parameterValues);
|
||||
|
||||
if(this.queryProvider == null) {
|
||||
if (this.queryProvider == null) {
|
||||
Assert.hasLength(this.selectClause, "selectClause is required when not providing a PagingQueryProvider");
|
||||
Assert.hasLength(this.fromClause, "fromClause is required when not providing a PagingQueryProvider");
|
||||
Assert.notEmpty(this.sortKeys, "sortKeys are required when not providing a PagingQueryProvider");
|
||||
@@ -354,23 +336,45 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
|
||||
switch (databaseType) {
|
||||
|
||||
case DERBY: provider = new DerbyPagingQueryProvider(); break;
|
||||
case DB2:
|
||||
case DB2VSE:
|
||||
case DB2ZOS:
|
||||
case DB2AS400: provider = new Db2PagingQueryProvider(); break;
|
||||
case H2: provider = new H2PagingQueryProvider(); break;
|
||||
case HANA: provider = new HanaPagingQueryProvider(); break;
|
||||
case HSQL: provider = new HsqlPagingQueryProvider(); break;
|
||||
case SQLSERVER: provider = new SqlServerPagingQueryProvider(); break;
|
||||
case MYSQL: provider = new MySqlPagingQueryProvider(); break;
|
||||
case ORACLE: provider = new OraclePagingQueryProvider(); break;
|
||||
case POSTGRES: provider = new PostgresPagingQueryProvider(); break;
|
||||
case SYBASE: provider = new SybasePagingQueryProvider(); break;
|
||||
case SQLITE: provider = new SqlitePagingQueryProvider(); break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unable to determine PagingQueryProvider type " +
|
||||
"from database type: " + databaseType);
|
||||
case DERBY:
|
||||
provider = new DerbyPagingQueryProvider();
|
||||
break;
|
||||
case DB2:
|
||||
case DB2VSE:
|
||||
case DB2ZOS:
|
||||
case DB2AS400:
|
||||
provider = new Db2PagingQueryProvider();
|
||||
break;
|
||||
case H2:
|
||||
provider = new H2PagingQueryProvider();
|
||||
break;
|
||||
case HANA:
|
||||
provider = new HanaPagingQueryProvider();
|
||||
break;
|
||||
case HSQL:
|
||||
provider = new HsqlPagingQueryProvider();
|
||||
break;
|
||||
case SQLSERVER:
|
||||
provider = new SqlServerPagingQueryProvider();
|
||||
break;
|
||||
case MYSQL:
|
||||
provider = new MySqlPagingQueryProvider();
|
||||
break;
|
||||
case ORACLE:
|
||||
provider = new OraclePagingQueryProvider();
|
||||
break;
|
||||
case POSTGRES:
|
||||
provider = new PostgresPagingQueryProvider();
|
||||
break;
|
||||
case SYBASE:
|
||||
provider = new SybasePagingQueryProvider();
|
||||
break;
|
||||
case SQLITE:
|
||||
provider = new SqlitePagingQueryProvider();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to determine PagingQueryProvider type " + "from database type: " + databaseType);
|
||||
}
|
||||
|
||||
provider.setSelectClause(this.selectClause);
|
||||
@@ -385,4 +389,5 @@ public class JdbcPagingItemReaderBuilder<T> {
|
||||
throw new IllegalArgumentException("Unable to determine PagingQueryProvider type", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,25 +30,29 @@ import org.springframework.util.Assert;
|
||||
* Builder for {@link JpaCursorItemReader}.
|
||||
*
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
public class JpaCursorItemReaderBuilder<T> {
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private JpaQueryProvider queryProvider;
|
||||
|
||||
private Map<String, Object> parameterValues;
|
||||
|
||||
private boolean saveState = true;
|
||||
|
||||
private String name;
|
||||
|
||||
private int maxItemCount = Integer.MAX_VALUE;
|
||||
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link ItemStreamSupport}
|
||||
* should be persisted within the {@link ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the {@link ItemStreamSupport} should be persisted within
|
||||
* the {@link ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -59,9 +63,8 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The name used to calculate the key within the {@link ExecutionContext}.
|
||||
* Required if {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* The name used to calculate the key within the {@link ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see ItemStreamSupport#setName(String)
|
||||
@@ -74,7 +77,6 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -87,7 +89,6 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -99,9 +100,8 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of parameter values to be set on the query. The key of the map is
|
||||
* the name of the parameter to be set with the value being the value to be set.
|
||||
*
|
||||
* A map of parameter values to be set on the query. The key of the map is the name of
|
||||
* the parameter to be set with the value being the value to be set.
|
||||
* @param parameterValues map of values
|
||||
* @return this instance for method chaining
|
||||
* @see JpaCursorItemReader#setParameterValues(Map)
|
||||
@@ -113,9 +113,8 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. This should be set only if {@link #queryString(String)}
|
||||
* have not been set.
|
||||
*
|
||||
* A query provider. This should be set only if {@link #queryString(String)} have not
|
||||
* been set.
|
||||
* @param queryProvider the query provider
|
||||
* @return this instance for method chaining
|
||||
* @see JpaCursorItemReader#setQueryProvider(JpaQueryProvider)
|
||||
@@ -129,7 +128,6 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* The JPQL query string to execute. This should only be set if
|
||||
* {@link #queryProvider(JpaQueryProvider)} has not been set.
|
||||
*
|
||||
* @param queryString the JPQL query
|
||||
* @return this instance for method chaining
|
||||
* @see JpaCursorItemReader#setQueryString(String)
|
||||
@@ -143,7 +141,6 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
/**
|
||||
* The {@link EntityManagerFactory} to be used for executing the configured
|
||||
* {@link #queryString}.
|
||||
*
|
||||
* @param entityManagerFactory {@link EntityManagerFactory} used to create
|
||||
* {@link jakarta.persistence.EntityManager}
|
||||
* @return this instance for method chaining
|
||||
@@ -156,7 +153,6 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully constructed {@link JpaCursorItemReader}.
|
||||
*
|
||||
* @return a new {@link JpaCursorItemReader}
|
||||
*/
|
||||
public JpaCursorItemReader<T> build() {
|
||||
@@ -179,4 +175,5 @@ public class JpaCursorItemReaderBuilder<T> {
|
||||
reader.setName(this.name);
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ import org.springframework.util.Assert;
|
||||
public class JpaItemWriterBuilder<T> {
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
private boolean usePersist = false;
|
||||
|
||||
/**
|
||||
* The JPA {@link EntityManagerFactory} to obtain an entity manager from. Required.
|
||||
*
|
||||
* @param entityManagerFactory the {@link EntityManagerFactory}
|
||||
* @return this instance for method chaining
|
||||
* @see JpaItemWriter#setEntityManagerFactory(EntityManagerFactory)
|
||||
@@ -47,7 +47,6 @@ public class JpaItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Set whether the entity manager should perform a persist instead of a merge.
|
||||
*
|
||||
* @param usePersist defaults to false
|
||||
* @return this instance for method chaining
|
||||
* @see JpaItemWriter#setUsePersist(boolean)
|
||||
@@ -60,12 +59,10 @@ public class JpaItemWriterBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully built {@link JpaItemWriter}.
|
||||
*
|
||||
* @return the writer
|
||||
*/
|
||||
public JpaItemWriter<T> build() {
|
||||
Assert.state(this.entityManagerFactory != null,
|
||||
"EntityManagerFactory must be provided");
|
||||
Assert.state(this.entityManagerFactory != null, "EntityManagerFactory must be provided");
|
||||
|
||||
JpaItemWriter<T> writer = new JpaItemWriter<>();
|
||||
writer.setEntityManagerFactory(this.entityManagerFactory);
|
||||
@@ -73,4 +70,5 @@ public class JpaItemWriterBuilder<T> {
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Glenn Renfro
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
@@ -54,10 +53,9 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
private int currentItemCount;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -71,7 +69,6 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -84,7 +81,6 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -97,7 +93,6 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -109,9 +104,8 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* The number of records to request per page/query. Defaults to 10. Must be greater
|
||||
* than zero.
|
||||
*
|
||||
* @param pageSize number of items
|
||||
* @return this instance for method chaining
|
||||
* @see JpaPagingItemReader#setPageSize(int)
|
||||
@@ -123,9 +117,8 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of parameter values to be set on the query. The key of the map is the name
|
||||
* of the parameter to be set with the value being the value to be set.
|
||||
*
|
||||
* A map of parameter values to be set on the query. The key of the map is the name of
|
||||
* the parameter to be set with the value being the value to be set.
|
||||
* @param parameterValues map of values
|
||||
* @return this instance for method chaining
|
||||
* @see JpaPagingItemReader#setParameterValues(Map)
|
||||
@@ -137,9 +130,8 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A query provider. This should be set only if {@link #queryString(String)} have not
|
||||
* A query provider. This should be set only if {@link #queryString(String)} have not
|
||||
* been set.
|
||||
*
|
||||
* @param queryProvider the query provider
|
||||
* @return this instance for method chaining
|
||||
* @see JpaPagingItemReader#setQueryProvider(JpaQueryProvider)
|
||||
@@ -151,9 +143,8 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* The HQL query string to execute. This should only be set if
|
||||
* {@link #queryProvider(JpaQueryProvider)} has not been set.
|
||||
*
|
||||
* @param queryString the HQL query
|
||||
* @return this instance for method chaining
|
||||
* @see JpaPagingItemReader#setQueryString(String)
|
||||
@@ -165,10 +156,10 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a transaction should be created around the read (true by default).
|
||||
* Can be set to false in cases where JPA implementation doesn't support a particular
|
||||
* transaction, however this may cause object inconsistency in the EntityManagerFactory.
|
||||
*
|
||||
* Indicates if a transaction should be created around the read (true by default). Can
|
||||
* be set to false in cases where JPA implementation doesn't support a particular
|
||||
* transaction, however this may cause object inconsistency in the
|
||||
* EntityManagerFactory.
|
||||
* @param transacted defaults to true
|
||||
* @return this instance for method chaining
|
||||
* @see JpaPagingItemReader#setTransacted(boolean)
|
||||
@@ -182,7 +173,6 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
/**
|
||||
* The {@link EntityManagerFactory} to be used for executing the configured
|
||||
* {@link #queryString}.
|
||||
*
|
||||
* @param entityManagerFactory {@link EntityManagerFactory} used to create
|
||||
* {@link jakarta.persistence.EntityManager}
|
||||
* @return this instance for method chaining
|
||||
@@ -195,19 +185,17 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Returns a fully constructed {@link JpaPagingItemReader}.
|
||||
*
|
||||
* @return a new {@link JpaPagingItemReader}
|
||||
*/
|
||||
public JpaPagingItemReader<T> build() {
|
||||
Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero");
|
||||
Assert.notNull(this.entityManagerFactory, "An EntityManagerFactory is required");
|
||||
|
||||
if(this.saveState) {
|
||||
Assert.hasText(this.name,
|
||||
"A name is required when saveState is set to true");
|
||||
if (this.saveState) {
|
||||
Assert.hasText(this.name, "A name is required when saveState is set to true");
|
||||
}
|
||||
|
||||
if(this.queryProvider == null) {
|
||||
if (this.queryProvider == null) {
|
||||
Assert.hasLength(this.queryString, "Query string is required when queryProvider is null");
|
||||
}
|
||||
|
||||
@@ -226,4 +214,5 @@ public class JpaPagingItemReaderBuilder<T> {
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,10 +76,9 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
|
||||
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
|
||||
* for restart purposes.
|
||||
*
|
||||
* Configure if the state of the
|
||||
* {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
*/
|
||||
@@ -93,7 +92,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link #saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.ItemStreamSupport#setName(String)
|
||||
@@ -106,7 +104,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
|
||||
@@ -119,7 +116,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Index for the current item. Used on restarts to indicate where to start from.
|
||||
*
|
||||
* @param currentItemCount current index
|
||||
* @return this instance for method chaining
|
||||
* @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
|
||||
@@ -132,7 +128,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The {@link DataSource} to read from
|
||||
*
|
||||
* @param dataSource a relational data base
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setDataSource(DataSource)
|
||||
@@ -145,7 +140,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* A hint to the driver as to how many rows to return with each fetch.
|
||||
*
|
||||
* @param fetchSize the hint
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setFetchSize(int)
|
||||
@@ -158,7 +152,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The max number of rows the {@link java.sql.ResultSet} can contain
|
||||
*
|
||||
* @param maxRows the max
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setMaxRows(int)
|
||||
@@ -171,7 +164,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The time in milliseconds for the query to timeout
|
||||
*
|
||||
* @param queryTimeout timeout
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setQueryTimeout(int)
|
||||
@@ -184,7 +176,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Indicates if SQL warnings should be ignored or if an exception should be thrown.
|
||||
*
|
||||
* @param ignoreWarnings indicator. Defaults to true
|
||||
* @return this instance for method chaining
|
||||
* @see AbstractCursorItemReader#setIgnoreWarnings(boolean)
|
||||
@@ -197,9 +188,8 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Indicates if the reader should verify the current position of the
|
||||
* {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults
|
||||
* to true.
|
||||
*
|
||||
* {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults to
|
||||
* true.
|
||||
* @param verifyCursorPosition indicator
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setVerifyCursorPosition(boolean)
|
||||
@@ -213,7 +203,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicates if the JDBC driver supports setting the absolute row on the
|
||||
* {@link java.sql.ResultSet}.
|
||||
*
|
||||
* @param driverSupportsAbsolute indicator
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setDriverSupportsAbsolute(boolean)
|
||||
@@ -227,7 +216,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
/**
|
||||
* Indicates that the connection used for the cursor is being used by all other
|
||||
* processing, therefor part of the same transaction.
|
||||
*
|
||||
* @param useSharedExtendedConnection indicator
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setUseSharedExtendedConnection(boolean)
|
||||
@@ -241,12 +229,12 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
/**
|
||||
* Configures the provided {@link PreparedStatementSetter} to be used to populate any
|
||||
* arguments in the SQL query to be executed for the reader.
|
||||
*
|
||||
* @param preparedStatementSetter setter
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setPreparedStatementSetter(PreparedStatementSetter)
|
||||
*/
|
||||
public StoredProcedureItemReaderBuilder<T> preparedStatementSetter(PreparedStatementSetter preparedStatementSetter) {
|
||||
public StoredProcedureItemReaderBuilder<T> preparedStatementSetter(
|
||||
PreparedStatementSetter preparedStatementSetter) {
|
||||
this.preparedStatementSetter = preparedStatementSetter;
|
||||
|
||||
return this;
|
||||
@@ -254,7 +242,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The {@link RowMapper} used to map the results of the cursor to each item.
|
||||
*
|
||||
* @param rowMapper {@link RowMapper}
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setRowMapper(RowMapper)
|
||||
@@ -267,7 +254,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* The name of the stored procedure to execute
|
||||
*
|
||||
* @param procedureName name of the procedure
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setProcedureName(String)
|
||||
@@ -280,7 +266,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* SQL parameters to be set when executing the stored procedure
|
||||
*
|
||||
* @param parameters parameters to be set
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setParameters(SqlParameter[])
|
||||
@@ -293,7 +278,6 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Indicates the stored procedure is a function
|
||||
*
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setFunction(boolean)
|
||||
*/
|
||||
@@ -304,9 +288,8 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL that
|
||||
* use REF CURSORs. For any other database, this should remain as the default (0).
|
||||
*
|
||||
* The parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL that
|
||||
* use REF CURSORs. For any other database, this should remain as the default (0).
|
||||
* @param refCursorPosition the parameter position
|
||||
* @return this instance for method chaining
|
||||
* @see StoredProcedureItemReader#setRefCursorPosition(int)
|
||||
@@ -319,13 +302,11 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
/**
|
||||
* Validates configuration and builds a new reader instance
|
||||
*
|
||||
* @return a fully constructed {@link StoredProcedureItemReader}
|
||||
*/
|
||||
public StoredProcedureItemReader<T> build() {
|
||||
if(this.saveState) {
|
||||
Assert.hasText(this.name,
|
||||
"A name is required when saveSate is set to true");
|
||||
if (this.saveState) {
|
||||
Assert.hasText(this.name, "A name is required when saveSate is set to true");
|
||||
}
|
||||
|
||||
Assert.notNull(this.procedureName, "The name of the stored procedure must be provided");
|
||||
@@ -334,7 +315,7 @@ public class StoredProcedureItemReaderBuilder<T> {
|
||||
|
||||
StoredProcedureItemReader<T> itemReader = new StoredProcedureItemReader<>();
|
||||
|
||||
if(StringUtils.hasText(this.name)) {
|
||||
if (StringUtils.hasText(this.name)) {
|
||||
itemReader.setName(this.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,23 +21,27 @@ import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
|
||||
/**
|
||||
* <p>Abstract Hibernate Query Provider to serve as a base class for all
|
||||
* Hibernate {@link Query} providers.</p>
|
||||
* <p>
|
||||
* Abstract Hibernate Query Provider to serve as a base class for all Hibernate
|
||||
* {@link Query} providers.
|
||||
* </p>
|
||||
*
|
||||
* <p>The implementing provider can be configured to use either
|
||||
* {@link StatelessSession} sufficient for simple mappings without the need
|
||||
* to cascade to associated objects or standard Hibernate {@link Session}
|
||||
* for more advanced mappings or when caching is desired.</p>
|
||||
* <p>
|
||||
* The implementing provider can be configured to use either {@link StatelessSession}
|
||||
* sufficient for simple mappings without the need to cascade to associated objects or
|
||||
* standard Hibernate {@link Session} for more advanced mappings or when caching is
|
||||
* desired.
|
||||
* </p>
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractHibernateQueryProvider<T> implements HibernateQueryProvider<T> {
|
||||
|
||||
private StatelessSession statelessSession;
|
||||
|
||||
private Session statefulSession;
|
||||
|
||||
@Override
|
||||
@@ -51,7 +55,7 @@ public abstract class AbstractHibernateQueryProvider<T> implements HibernateQuer
|
||||
}
|
||||
|
||||
public boolean isStatelessSession() {
|
||||
return this.statefulSession==null && this.statelessSession!=null;
|
||||
return this.statefulSession == null && this.statelessSession != null;
|
||||
}
|
||||
|
||||
protected StatelessSession getStatelessSession() {
|
||||
@@ -61,4 +65,5 @@ public abstract class AbstractHibernateQueryProvider<T> implements HibernateQuer
|
||||
protected Session getStatefulSession() {
|
||||
return statefulSession;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,13 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Abstract JPA Query Provider to serve as a base class for all JPA
|
||||
* {@link Query} providers.
|
||||
* Abstract JPA Query Provider to serve as a base class for all JPA {@link Query}
|
||||
* providers.
|
||||
* </p>
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, InitializingBean {
|
||||
@@ -43,7 +42,6 @@ public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, Init
|
||||
* {@link HibernateQueryProvider}. This is currently needed to allow
|
||||
* {@link HibernateQueryProvider} to participate in a user's managed transaction.
|
||||
* </p>
|
||||
*
|
||||
* @param entityManager EntityManager to use
|
||||
*/
|
||||
@Override
|
||||
@@ -55,10 +53,10 @@ public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, Init
|
||||
* <p>
|
||||
* Getter for {@link EntityManager}
|
||||
* </p>
|
||||
*
|
||||
* @return entityManager the injected {@link EntityManager}
|
||||
*/
|
||||
protected EntityManager getEntityManager() {
|
||||
return entityManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,13 +24,12 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This query provider creates Hibernate {@link Query}s from injected native SQL
|
||||
* queries. This is useful if there is a need to utilize database-specific
|
||||
* features such as query hints, the CONNECT keyword in Oracle, etc.
|
||||
* This query provider creates Hibernate {@link Query}s from injected native SQL queries.
|
||||
* This is useful if there is a need to utilize database-specific features such as query
|
||||
* hints, the CONNECT keyword in Oracle, etc.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
*
|
||||
* @param <E> entity returned by executing the query
|
||||
*/
|
||||
public class HibernateNativeQueryProvider<E> extends AbstractHibernateQueryProvider<E> {
|
||||
@@ -41,11 +40,11 @@ public class HibernateNativeQueryProvider<E> extends AbstractHibernateQueryProvi
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Create an {@link NativeQuery} from the session provided (preferring
|
||||
* stateless if both are available).
|
||||
* Create an {@link NativeQuery} from the session provided (preferring stateless if
|
||||
* both are available).
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public NativeQuery<E> createQuery() {
|
||||
|
||||
@@ -69,4 +68,5 @@ public class HibernateNativeQueryProvider<E> extends AbstractHibernateQueryProvi
|
||||
Assert.isTrue(StringUtils.hasText(sqlQuery), "Native SQL query cannot be empty");
|
||||
Assert.notNull(entityClass, "Entity class cannot be NULL");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,15 +23,14 @@ import org.springframework.batch.item.ItemReader;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Interface defining the functionality to be provided for generating queries
|
||||
* for use with Hibernate {@link ItemReader}s or other custom built artifacts.
|
||||
* Interface defining the functionality to be provided for generating queries for use with
|
||||
* Hibernate {@link ItemReader}s or other custom built artifacts.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.1
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface HibernateQueryProvider<T> {
|
||||
|
||||
@@ -40,37 +39,33 @@ public interface HibernateQueryProvider<T> {
|
||||
* Create the query object which type will be determined by the underline
|
||||
* implementation (e.g. Hibernate, JPA, etc.)
|
||||
* </p>
|
||||
*
|
||||
* @return created query
|
||||
*/
|
||||
Query<T> createQuery();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inject a {@link Session} that can be used as a factory for queries. The
|
||||
* state of the session is controlled by the caller (i.e. it should be
|
||||
* closed if necessary).
|
||||
* Inject a {@link Session} that can be used as a factory for queries. The state of
|
||||
* the session is controlled by the caller (i.e. it should be closed if necessary).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Use either this method or {@link #setStatelessSession(StatelessSession)}
|
||||
* </p>
|
||||
*
|
||||
* @param session the {@link Session} to set
|
||||
*/
|
||||
void setSession(Session session);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inject a {@link StatelessSession} that can be used as a factory for
|
||||
* queries. The state of the session is controlled by the caller (i.e. it
|
||||
* should be closed if necessary).
|
||||
* Inject a {@link StatelessSession} that can be used as a factory for queries. The
|
||||
* state of the session is controlled by the caller (i.e. it should be closed if
|
||||
* necessary).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Use either this method or {@link #setSession(Session)}
|
||||
* </p>
|
||||
*
|
||||
* @param session the {@link StatelessSession} to set
|
||||
*/
|
||||
void setStatelessSession(StatelessSession session);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @author Parikshit Dutta
|
||||
* @since 4.3
|
||||
*
|
||||
* @param <E> entity returned by executing the query
|
||||
*/
|
||||
public class JpaNamedQueryProvider<E> extends AbstractJpaQueryProvider {
|
||||
@@ -61,4 +60,5 @@ public class JpaNamedQueryProvider<E> extends AbstractJpaQueryProvider {
|
||||
Assert.isTrue(StringUtils.hasText(this.namedQuery), "Named query cannot be empty");
|
||||
Assert.notNull(this.entityClass, "Entity class cannot be NULL");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,13 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This query provider creates JPA {@link Query}s from injected native SQL
|
||||
* queries. This is useful if there is a need to utilize database-specific
|
||||
* features such as query hints, the CONNECT keyword in Oracle, etc.
|
||||
* This query provider creates JPA {@link Query}s from injected native SQL queries. This
|
||||
* is useful if there is a need to utilize database-specific features such as query hints,
|
||||
* the CONNECT keyword in Oracle, etc.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
* @param <E> entity returned by executing the query
|
||||
*/
|
||||
public class JpaNativeQueryProvider<E> extends AbstractJpaQueryProvider {
|
||||
@@ -39,7 +38,7 @@ public class JpaNativeQueryProvider<E> extends AbstractJpaQueryProvider {
|
||||
|
||||
private String sqlQuery;
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Query createQuery() {
|
||||
return getEntityManager().createNativeQuery(sqlQuery, entityClass);
|
||||
}
|
||||
@@ -52,9 +51,10 @@ public class JpaNativeQueryProvider<E> extends AbstractJpaQueryProvider {
|
||||
this.entityClass = entityClazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.isTrue(StringUtils.hasText(sqlQuery), "Native SQL query cannot be empty");
|
||||
Assert.notNull(entityClass, "Entity class cannot be NULL");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,29 +22,31 @@ import jakarta.persistence.Query;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
|
||||
/**
|
||||
* <p>Interface defining the functionality to be provided for generating queries
|
||||
* for use with JPA {@link ItemReader}s or other custom built artifacts.</p>
|
||||
*
|
||||
* <p>
|
||||
* Interface defining the functionality to be provided for generating queries for use with
|
||||
* JPA {@link ItemReader}s or other custom built artifacts.
|
||||
* </p>
|
||||
*
|
||||
* @author Anatoly Polinsky
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 2.1
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface JpaQueryProvider {
|
||||
|
||||
/**
|
||||
* <p>Create the query object.</p>
|
||||
*
|
||||
* @return created query
|
||||
*/
|
||||
/**
|
||||
* <p>
|
||||
* Create the query object.
|
||||
* </p>
|
||||
* @return created query
|
||||
*/
|
||||
public Query createQuery();
|
||||
|
||||
/**
|
||||
* Provide an {@link EntityManager} for the query to be built.
|
||||
*
|
||||
* @param entityManager to be used by the {@link JpaQueryProvider}.
|
||||
*/
|
||||
void setEntityManager(EntityManager entityManager);
|
||||
|
||||
/**
|
||||
* Provide an {@link EntityManager} for the query to be built.
|
||||
* @param entityManager to be used by the {@link JpaQueryProvider}.
|
||||
*/
|
||||
void setEntityManager(EntityManager entityManager);
|
||||
|
||||
}
|
||||
|
||||
@@ -30,22 +30,21 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract SQL Paging Query Provider to serve as a base class for all provided
|
||||
* SQL paging query providers.
|
||||
*
|
||||
* Any implementation must provide a way to specify the select clause, from
|
||||
* clause and optionally a where clause. In addition a way to specify a single
|
||||
* column sort key must also be provided. This sort key will be used to provide
|
||||
* the paging functionality. It is recommended that there should be an index for
|
||||
* the sort key to provide better performance.
|
||||
*
|
||||
* Provides properties and preparation for the mandatory "selectClause" and
|
||||
* "fromClause" as well as for the optional "whereClause". Also provides
|
||||
* property for the mandatory "sortKeys". <b>Note:</b> The columns that make up
|
||||
* the sort key must be a true key and not just a column to order by. It is important
|
||||
* to have a unique key constraint on the sort key to guarantee that no data is lost
|
||||
* between executions.
|
||||
*
|
||||
* Abstract SQL Paging Query Provider to serve as a base class for all provided SQL paging
|
||||
* query providers.
|
||||
*
|
||||
* Any implementation must provide a way to specify the select clause, from clause and
|
||||
* optionally a where clause. In addition a way to specify a single column sort key must
|
||||
* also be provided. This sort key will be used to provide the paging functionality. It is
|
||||
* recommended that there should be an index for the sort key to provide better
|
||||
* performance.
|
||||
*
|
||||
* Provides properties and preparation for the mandatory "selectClause" and "fromClause"
|
||||
* as well as for the optional "whereClause". Also provides property for the mandatory
|
||||
* "sortKeys". <b>Note:</b> The columns that make up the sort key must be a true key and
|
||||
* not just a column to order by. It is important to have a unique key constraint on the
|
||||
* sort key to guarantee that no data is lost between executions.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
@@ -60,7 +59,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
private String fromClause;
|
||||
|
||||
private String whereClause;
|
||||
|
||||
|
||||
private Map<String, Order> sortKeys = new LinkedHashMap<>();
|
||||
|
||||
private String groupClause;
|
||||
@@ -68,10 +67,9 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
private int parameterCount;
|
||||
|
||||
private boolean usingNamedParameters;
|
||||
|
||||
|
||||
/**
|
||||
* The setter for the group by clause
|
||||
*
|
||||
* @param groupClause SQL GROUP BY clause part of the SQL query string
|
||||
*/
|
||||
public void setGroupClause(String groupClause) {
|
||||
@@ -82,10 +80,9 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
this.groupClause = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The getter for the group by clause
|
||||
*
|
||||
* @return SQL GROUP BY clause part of the SQL query string
|
||||
*/
|
||||
public String getGroupClause() {
|
||||
@@ -100,7 +97,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL SELECT clause part of SQL query string
|
||||
*/
|
||||
protected String getSelectClause() {
|
||||
@@ -115,7 +111,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL FROM clause part of SQL query string
|
||||
*/
|
||||
protected String getFromClause() {
|
||||
@@ -135,7 +130,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL WHERE clause part of SQL query string
|
||||
*/
|
||||
protected String getWhereClause() {
|
||||
@@ -150,32 +144,31 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
* A Map<String, Boolean> of sort columns as the key and boolean for ascending/descending (ascending = true).
|
||||
*
|
||||
* A Map<String, Boolean> of sort columns as the key and boolean for
|
||||
* ascending/descending (ascending = true).
|
||||
* @return sortKey key to use to sort and limit page content
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public Map<String, Order> getSortKeys() {
|
||||
return sortKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int getParameterCount() {
|
||||
return parameterCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public boolean isUsingNamedParameters() {
|
||||
return usingNamedParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sort key placeholder will vary depending on whether named parameters
|
||||
* or traditional placeholders are used in query strings.
|
||||
*
|
||||
* The sort key placeholder will vary depending on whether named parameters or
|
||||
* traditional placeholders are used in query strings.
|
||||
* @return place holder for sortKey.
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public String getSortKeyPlaceHolder(String keyName) {
|
||||
return usingNamedParameters ? ":_" + keyName : "?";
|
||||
}
|
||||
@@ -184,7 +177,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
* Check mandatory properties.
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public void init(DataSource dataSource) throws Exception {
|
||||
Assert.notNull(dataSource, "A DataSource is required");
|
||||
Assert.hasLength(selectClause, "selectClause must be specified");
|
||||
@@ -196,7 +189,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
if (whereClause != null) {
|
||||
sql.append(" WHERE ").append(whereClause);
|
||||
}
|
||||
if(groupClause != null) {
|
||||
if (groupClause != null) {
|
||||
sql.append(" GROUP BY ").append(groupClause);
|
||||
}
|
||||
List<String> namedParameters = new ArrayList<>();
|
||||
@@ -211,40 +204,38 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
* Method generating the query string to be used for retrieving the first
|
||||
* page. This method must be implemented in sub classes.
|
||||
*
|
||||
* Method generating the query string to be used for retrieving the first page. This
|
||||
* method must be implemented in sub classes.
|
||||
* @param pageSize number of rows to read per page
|
||||
* @return query string
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public abstract String generateFirstPageQuery(int pageSize);
|
||||
|
||||
/**
|
||||
* Method generating the query string to be used for retrieving the pages
|
||||
* following the first page. This method must be implemented in sub classes.
|
||||
*
|
||||
* Method generating the query string to be used for retrieving the pages following
|
||||
* the first page. This method must be implemented in sub classes.
|
||||
* @param pageSize number of rows to read per page
|
||||
* @return query string
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public abstract String generateRemainingPagesQuery(int pageSize);
|
||||
|
||||
/**
|
||||
* Method generating the query string to be used for jumping to a specific
|
||||
* item position. This method must be implemented in sub classes.
|
||||
*
|
||||
* Method generating the query string to be used for jumping to a specific item
|
||||
* position. This method must be implemented in sub classes.
|
||||
* @param itemIndex the index of the item to jump to
|
||||
* @param pageSize number of rows to read per page
|
||||
* @return query string
|
||||
*/
|
||||
@Override
|
||||
@Override
|
||||
public abstract String generateJumpToItemQuery(int itemIndex, int pageSize);
|
||||
|
||||
private String removeKeyWord(String keyWord, String clause) {
|
||||
String temp = clause.trim();
|
||||
int length = keyWord.length();
|
||||
if (temp.toLowerCase().startsWith(keyWord) && Character.isWhitespace(temp.charAt(length)) && temp.length() > length + 1) {
|
||||
if (temp.toLowerCase().startsWith(keyWord) && Character.isWhitespace(temp.charAt(length))
|
||||
&& temp.length() > length + 1) {
|
||||
return temp.substring(length + 1);
|
||||
}
|
||||
else {
|
||||
@@ -253,7 +244,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return sortKey key to use to sort and limit page content (without alias)
|
||||
*/
|
||||
@Override
|
||||
@@ -268,11 +258,13 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
if (columnIndex < key.length()) {
|
||||
sortKeysWithoutAliases.put(key.substring(columnIndex), sortKeyEntry.getValue());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sortKeysWithoutAliases.put(sortKeyEntry.getKey(), sortKeyEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return sortKeysWithoutAliases;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>Implementation of the {@link ItemPreparedStatementSetter} interface that assumes all
|
||||
* keys are contained within a {@link Map} with the column name as the key. It assumes nothing
|
||||
* about ordering, and assumes that the order the entry set can be iterated over is the same as
|
||||
* the PreparedStatement should be set.</p>
|
||||
*
|
||||
* <p>
|
||||
* Implementation of the {@link ItemPreparedStatementSetter} interface that assumes all
|
||||
* keys are contained within a {@link Map} with the column name as the key. It assumes
|
||||
* nothing about ordering, and assumes that the order the entry set can be iterated over
|
||||
* is the same as the PreparedStatement should be set.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @see ItemPreparedStatementSetter
|
||||
@@ -39,11 +41,11 @@ import java.util.Map;
|
||||
*/
|
||||
public class ColumnMapItemPreparedStatementSetter implements ItemPreparedStatementSetter<Map<String, Object>> {
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void setValues(Map<String, Object> item, PreparedStatement ps) throws SQLException {
|
||||
Assert.isInstanceOf(Map.class, item, "Input to map PreparedStatement parameters must be of type Map.");
|
||||
int counter = 1;
|
||||
for(Object value : item.values()){
|
||||
for (Object value : item.values()) {
|
||||
StatementCreatorUtils.setParameterValue(ps, counter, SqlTypeValue.TYPE_UNKNOWN, value);
|
||||
counter++;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ package org.springframework.batch.item.database.support;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link DataFieldMaxValueIncrementer} implementations
|
||||
* based upon a provided string.
|
||||
*
|
||||
* Factory for creating {@link DataFieldMaxValueIncrementer} implementations based upon a
|
||||
* provided string.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
@@ -28,29 +28,28 @@ public interface DataFieldMaxValueIncrementerFactory {
|
||||
|
||||
/**
|
||||
* Return the {@link DataFieldMaxValueIncrementer} for the provided database type.
|
||||
*
|
||||
* @param databaseType string represented database type
|
||||
* @param incrementerName incrementer name to create. In many cases this may be the
|
||||
* sequence name
|
||||
* sequence name
|
||||
* @return incrementer
|
||||
* @throws IllegalArgumentException if databaseType is invalid type, or incrementerName
|
||||
* is null.
|
||||
* @throws IllegalArgumentException if databaseType is invalid type, or
|
||||
* incrementerName is null.
|
||||
*/
|
||||
public DataFieldMaxValueIncrementer getIncrementer(String databaseType, String incrementerName);
|
||||
|
||||
|
||||
/**
|
||||
* Returns boolean indicated whether or not the provided string is supported by this
|
||||
* factory.
|
||||
*
|
||||
* @param databaseType {@link String} containing the database type.
|
||||
* @return true if the incrementerType is supported by this database type. Else false is returned.
|
||||
* @return true if the incrementerType is supported by this database type. Else false
|
||||
* is returned.
|
||||
*/
|
||||
public boolean isSupportedIncrementerType(String databaseType);
|
||||
|
||||
/**
|
||||
* Returns the list of supported database incrementer types
|
||||
*
|
||||
* @return an array of {@link String}s containing the supported incrementer types.
|
||||
* @return an array of {@link String}s containing the supported incrementer types.
|
||||
*/
|
||||
public String[] getSupportedIncrementerTypes();
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ import org.springframework.batch.item.database.PagingQueryProvider;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* DB2 implementation of a {@link PagingQueryProvider} using
|
||||
* database specific features.
|
||||
* DB2 implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Michael Minella
|
||||
@@ -37,7 +36,7 @@ public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String generateRemainingPagesQuery(int pageSize) {
|
||||
if(StringUtils.hasText(getGroupClause())) {
|
||||
if (StringUtils.hasText(getGroupClause())) {
|
||||
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -48,12 +48,12 @@ import static org.springframework.batch.support.DatabaseType.SQLSERVER;
|
||||
import static org.springframework.batch.support.DatabaseType.SYBASE;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link DataFieldMaxValueIncrementerFactory}
|
||||
* interface. Valid database types are given by the {@link DatabaseType} enum.
|
||||
* Default implementation of the {@link DataFieldMaxValueIncrementerFactory} interface.
|
||||
* Valid database types are given by the {@link DatabaseType} enum.
|
||||
*
|
||||
* Note: For MySql databases, the
|
||||
* {@link MySQLMaxValueIncrementer#setUseNewConnection(boolean)} will be set to true.
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Michael Minella
|
||||
* @author Drummond Dawson
|
||||
@@ -67,11 +67,10 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
|
||||
private String incrementerColumnName = "ID";
|
||||
|
||||
/**
|
||||
* Public setter for the column name (defaults to "ID") in the incrementer.
|
||||
* Only used by some platforms (Derby, HSQL, MySQL, SQL Server and Sybase),
|
||||
* and should be fine for use with Spring Batch meta data as long as the
|
||||
* default batch schema hasn't been changed.
|
||||
*
|
||||
* Public setter for the column name (defaults to "ID") in the incrementer. Only used
|
||||
* by some platforms (Derby, HSQL, MySQL, SQL Server and Sybase), and should be fine
|
||||
* for use with Spring Batch meta data as long as the default batch schema hasn't been
|
||||
* changed.
|
||||
* @param incrementerColumnName the primary key column name to set
|
||||
*/
|
||||
public void setIncrementerColumnName(String incrementerColumnName) {
|
||||
@@ -105,7 +104,8 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
|
||||
return new HanaSequenceMaxValueIncrementer(dataSource, incrementerName);
|
||||
}
|
||||
else if (databaseType == MYSQL) {
|
||||
MySQLMaxValueIncrementer mySQLMaxValueIncrementer = new MySQLMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
|
||||
MySQLMaxValueIncrementer mySQLMaxValueIncrementer = new MySQLMaxValueIncrementer(dataSource,
|
||||
incrementerName, incrementerColumnName);
|
||||
mySQLMaxValueIncrementer.setUseNewConnection(true);
|
||||
return mySQLMaxValueIncrementer;
|
||||
}
|
||||
@@ -126,8 +126,8 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
|
||||
}
|
||||
throw new IllegalArgumentException("databaseType argument was not on the approved list");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public boolean isSupportedIncrementerType(String incrementerType) {
|
||||
for (DatabaseType type : DatabaseType.values()) {
|
||||
if (type.name().equalsIgnoreCase(incrementerType)) {
|
||||
@@ -138,7 +138,7 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public String[] getSupportedIncrementerTypes() {
|
||||
|
||||
List<String> types = new ArrayList<>();
|
||||
@@ -149,4 +149,5 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
|
||||
|
||||
return types.toArray(new String[types.size()]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,11 +24,11 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
|
||||
/**
|
||||
* Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing functions.
|
||||
* These features are supported starting with Apache Derby version 10.4.1.3.
|
||||
* Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing
|
||||
* functions. These features are supported starting with Apache Derby version 10.4.1.3.
|
||||
*
|
||||
* As the OVER() function does not support the ORDER BY clause a sub query is instead used to order the results
|
||||
* before the ROW_NUM restriction is applied
|
||||
* As the OVER() function does not support the ORDER BY clause a sub query is instead used
|
||||
* to order the results before the ROW_NUM restriction is applied
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author David Thexton
|
||||
@@ -36,7 +36,7 @@ import org.springframework.jdbc.support.JdbcUtils;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
|
||||
|
||||
|
||||
private static final String MINIMAL_DERBY_VERSION = "10.4.1.3";
|
||||
|
||||
@Override
|
||||
@@ -44,11 +44,14 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
|
||||
super.init(dataSource);
|
||||
String version = JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductVersion);
|
||||
if (!isDerbyVersionSupported(version)) {
|
||||
throw new InvalidDataAccessResourceUsageException("Apache Derby version " + version + " is not supported by this class, Only version " + MINIMAL_DERBY_VERSION + " or later is supported");
|
||||
throw new InvalidDataAccessResourceUsageException(
|
||||
"Apache Derby version " + version + " is not supported by this class, Only version "
|
||||
+ MINIMAL_DERBY_VERSION + " or later is supported");
|
||||
}
|
||||
}
|
||||
|
||||
// derby version numbering is M.m.f.p [ {alpha|beta} ] see https://db.apache.org/derby/papers/versionupgrade.html#Basic+Numbering+Scheme
|
||||
|
||||
// derby version numbering is M.m.f.p [ {alpha|beta} ] see
|
||||
// https://db.apache.org/derby/papers/versionupgrade.html#Basic+Numbering+Scheme
|
||||
private boolean isDerbyVersionSupported(String version) {
|
||||
String[] minimalVersionParts = MINIMAL_DERBY_VERSION.split("\\.");
|
||||
String[] versionParts = version.split("[\\. ]");
|
||||
@@ -57,13 +60,14 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
|
||||
int versionPart = Integer.parseInt(versionParts[i]);
|
||||
if (versionPart < minimalVersionPart) {
|
||||
return false;
|
||||
} else if (versionPart > minimalVersionPart) {
|
||||
}
|
||||
else if (versionPart > minimalVersionPart) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getOrderedQueryAlias() {
|
||||
return "TMP_ORDERED";
|
||||
@@ -74,12 +78,12 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
protected String getOverSubstituteClauseStart() {
|
||||
return " FROM (SELECT " + getSelectClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
protected String getOverSubstituteClauseEnd() {
|
||||
return " ) AS " + getOrderedQueryAlias();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.springframework.batch.item.database.support;
|
||||
|
||||
/**
|
||||
* H2 implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features.
|
||||
* H2 implementation of a
|
||||
* {@link org.springframework.batch.item.database.PagingQueryProvider} using database
|
||||
* specific features.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Henning Pöttker
|
||||
@@ -43,10 +45,9 @@ public class H2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
|
||||
int page = itemIndex / pageSize;
|
||||
int offset = (page * pageSize) - 1;
|
||||
offset = offset<0 ? 0 : offset;
|
||||
offset = offset < 0 ? 0 : offset;
|
||||
|
||||
String limitClause = new StringBuilder().append("OFFSET ")
|
||||
.append(offset).append(" ROWS FETCH NEXT 1 ROWS ONLY")
|
||||
String limitClause = new StringBuilder().append("OFFSET ").append(offset).append(" ROWS FETCH NEXT 1 ROWS ONLY")
|
||||
.toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import org.springframework.batch.item.database.PagingQueryProvider;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* SAP HANA implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
* SAP HANA implementation of a {@link PagingQueryProvider} using database specific
|
||||
* features.
|
||||
*
|
||||
* @author Jonathan Bregler
|
||||
* @since 5.0
|
||||
@@ -34,7 +35,7 @@ public class HanaPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String generateRemainingPagesQuery(int pageSize) {
|
||||
if(StringUtils.hasText(getGroupClause())) {
|
||||
if (StringUtils.hasText(getGroupClause())) {
|
||||
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize));
|
||||
}
|
||||
else {
|
||||
@@ -50,7 +51,7 @@ public class HanaPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
|
||||
int page = itemIndex / pageSize;
|
||||
int offset = (page * pageSize) - 1;
|
||||
offset = offset<0 ? 0 : offset;
|
||||
offset = offset < 0 ? 0 : offset;
|
||||
String limitClause = new StringBuilder().append("LIMIT 1 OFFSET ").append(offset).toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ package org.springframework.batch.item.database.support;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* HSQLDB implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features.
|
||||
* HSQLDB implementation of a
|
||||
* {@link org.springframework.batch.item.database.PagingQueryProvider} using database
|
||||
* specific features.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Michael Minella
|
||||
@@ -34,7 +36,7 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String generateRemainingPagesQuery(int pageSize) {
|
||||
if(StringUtils.hasText(getGroupClause())) {
|
||||
if (StringUtils.hasText(getGroupClause())) {
|
||||
return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize));
|
||||
}
|
||||
else {
|
||||
@@ -50,7 +52,7 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
|
||||
int page = itemIndex / pageSize;
|
||||
int offset = (page * pageSize) - 1;
|
||||
offset = offset<0 ? 0 : offset;
|
||||
offset = offset < 0 ? 0 : offset;
|
||||
|
||||
String topClause = new StringBuilder().append("LIMIT ").append(offset).append(" 1").toString();
|
||||
return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause);
|
||||
|
||||
@@ -36,7 +36,7 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String generateRemainingPagesQuery(int pageSize) {
|
||||
if(StringUtils.hasText(getGroupClause())) {
|
||||
if (StringUtils.hasText(getGroupClause())) {
|
||||
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize));
|
||||
}
|
||||
else {
|
||||
@@ -52,7 +52,7 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
|
||||
int page = itemIndex / pageSize;
|
||||
int offset = (page * pageSize) - 1;
|
||||
offset = offset<0 ? 0 : offset;
|
||||
offset = offset < 0 ? 0 : offset;
|
||||
|
||||
String limitClause = new StringBuilder().append("LIMIT ").append(offset).append(", 1").toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user