Class BulkQuery
Suppose one has a Collection of items and wants to pose a query to the database for each of those items. This can be quite a performance and throughput hog, since the overhead of a query execution is payed for each single item:
select 1 from atable where y='red' and x=1; select 1 from atable where y='red' and x=2; select 1 from atable where y='red' and x=3; ...
Often, the situation can be dealt with quite efficiently by using an IN-query.
select x from atable where y='red' and x IN (1,2,3,...);
The BulkQuery class provides a convenient abstraction to use this metaphor. The typical use would be as follows:
- First a BulkQuery instance is created.
- Then, the parameters which are different for each item are added via add.
- Afterwards, the query is specified along with the position (1-based) of the column of the result set one is interested in; this typically is 1.
- The result of the query execution is a Set<String> instance which can be used to determine if the query had a result for a particular item.
Example:
BulkQuery bQ = new BulkQuery(); for (Enumeration elems = v.elements(); elems.hasMoreElements();) { MyElement e = (MyElement) elems.nextElement(); bQ.add(Long.toString(MyElement.getOid())); } String query = "select x from atable where y='red' and x IN(?)"; Set<String> result = bQ.executeSet(query,1); for (Enumeration elems = v.elements(); elems.hasMoreElements();) { MyElement e = (MyElement) elems.nextElement(); if (result.contains(Long.toString(MyElement.getOid()))) { ... } else { ... }
But the BulkQuery can also be used if a collection of persistent objects should be retrieved using an IN-query for better performance. The usage is quite similar to the example above, only a different 'execute' method (
execute(Class,String)
) must be used to achieve this goal.
Example:
BulkQuery bQ = new BulkQuery(); for (Enumeration elems = v.elements(); elems.hasMoreElements();) { MyElement e = (MyElement) elems.nextElement(); MyReferencedElement ref = e.getReferencedElement(); bQ.add(Long.toString(ref.getOid())); } String condition = "oid in (?)"; Collection result = bQ.execute(MyReferencedElement.class, condition); ...
If you happen to have a conveniently structured pre-splitted list of values already at hand (like the splitResult when
Worklist.getAdditionalData(List)
is called),
you can construct a BulkQuery with the alternative Constructor. The elements of the Collection are Strings
which contain comma separated values.
Example:
BulkQuery bQ = new BulkQuery(splitResult,true); String aquery = "select oid from a_table where process in (?)"; Map result1 = bQ.execute(aquery,1); ... String bquery = "select oid from b_table where process in (?)"; Map result2 = bQ.execute(bquery,1); ...
For all execute methods there exists a variant with an extended parameter list where an parameter list containing additional bind variables can be specified. These variables are incorporated in the query as parameters in a prepared JDBC statement.
Since the placeholders for the JDBC bind variables must be specified by
?
,
the in-list in a query given to such an execute method must be exactly denoted by IN(?)
(in contrast
to the case without bind variables where it can be denoted just by a single ?
).
It is recommended to use the IN
constant, since it provides a value which is appropriate in every case.
Example:
BulkQuery bQ = new BulkQuery(); for (Enumeration elems = v.elements(); elems.hasMoreElements();) { MyElement e = (MyElement) elems.nextElement(); bQ.add(Long.toString(MyElement.getOid())); } String query = "select x from atable where started>=? and started <= ? and x "+BulkQuery.IN"; Map result = bQ.execute(query,1,fromDate,toDate); for (Enumeration elems = v.elements(); elems.hasMoreElements();) { MyElement e = (MyElement) elems.nextElement(); if (result.containsKey(Long.toString(MyElement.getOid()))) { ... } else { ... }
Note: due to restrictions in the implementations of SQL by the various DBMS, a BulkQuery with a long list of IN parameters might be executed more than once. E.g. first with the first hundred in-list parameters then again with the next hundred parameters and so on. This behavior alters the semantics of the query when using NOT IN(?).
-
Field Summary
-
Constructor Summary
ConstructorDescriptionConstruct a fresh BulkQuery.BulkQuery
(int splitSize) Construct a fresh BulkQuery and set a split sizeBulkQuery
(Collection<?> c) Construct a fresh BulkQuery and add each of the elements of the Collection.BulkQuery
(Collection<?> c, boolean isSplitted) Construct a fresh BulkQuery and add the elements of the Collection. -
Method Summary
Modifier and TypeMethodDescriptionvoid
add
(long l) Add a long to the query.void
add
(Persistent p) Add the oid of a Persistent to the query.void
Add a Long to the query.void
Add a String to the query.void
add
(Collection<?> c, boolean isSplitted) Add the elements of the Collection to a BulkQuery.void
Add a String to the query.int
Count the number of members of a given class matching the given condition based on the current elements.<T> List<T>
Execute the condition based on the current elements.<T> List<T>
Execute the condition based on the current elements.Deprecated.Deprecated.since 8.0; useexecuteSet(String,int,Object...)
instead<P> List<P>
Execute the query based on the current elements.<P> List<P>
Execute the query based on the current elements.executeSet
(String query, int pos) Execute the query based on the current elements.executeSet
(String query, int pos, Object... bindVars) Execute the query based on the current elements.int
int
setSplitSize
(int splitSize)
-
Field Details
-
IN
Marker for the in-List in the BulkQuery- See Also:
-
-
Constructor Details
-
BulkQuery
public BulkQuery()Construct a fresh BulkQuery. -
BulkQuery
public BulkQuery(int splitSize) Construct a fresh BulkQuery and set a split size -
BulkQuery
Construct a fresh BulkQuery and add each of the elements of the Collection. The elements must either beString
objects,Long
objects or implement thePersistent
interface.- Parameters:
c
- the Collection whose elements are added to the BulkQuery.
-
BulkQuery
Construct a fresh BulkQuery and add the elements of the Collection.- Parameters:
c
- the Collection whose elements are added to the BulkQuery.isSplitted
- if false, each of the (String or Persistent) elements of the Collection c are added; behaves likeBulkQuery(Collection)
. If isSplitted is true, the Collection is assumed to be already splitted to a convenient size. Each of the elements of the Collection must be a String in the form of a comma separated list of values. No single String should have more thangetSplitSize()
values, else the query might fail.
-
-
Method Details
-
add
Add the elements of the Collection to a BulkQuery.- Parameters:
c
- the Collection whose elements are added to the BulkQuery.isSplitted
- if false, each of the (String or Persistent) elements of the Collection c are added; behaves likeBulkQuery(Collection)
. If isSplitted is true, the Collection is assumed to be already splitted to a convenient size. Each of the elements of the Collection must be a String in the form of a comma separated list of values. No single String should have more thangetSplitSize()
values, else the query might fail.
-
add
Add a String to the query. The String is added without any conversions or quoting.- Parameters:
s
- the String to be added.
-
addQuoted
Add a String to the query.- Parameters:
s
- the String to be added. Single quotes within the string will be properly escaped for SQL (they will be duplicated). The string will be enclosed in single quotes.
addQuotes("Name: 'Erwin'") is the same as add("'Name: ''Erwin'''")
-
add
Add the oid of a Persistent to the query.- Parameters:
p
- the Persistent, which oid is to be added.
-
add
Add a Long to the query.- Parameters:
l
- the Long to be added.
-
add
public void add(long l) Add a long to the query.- Parameters:
l
- the long to be added.
-
getSplitSize
public int getSplitSize() -
setSplitSize
public int setSplitSize(int splitSize) -
execute
Deprecated.since 8.0; useexecuteSet(String,int)
insteadExecute the query based on the current elements.The query text must be a valid SQL statement. A question mark
?
value in this string indicates the position of the varying parameters (the IN-List). Thepos
argument indicates which column of the SQL ResultSet should be used to construct the returned Map object.- Parameters:
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.- Returns:
- A Map of the results of the query..
-
executeSet
Execute the query based on the current elements.The query text must be a valid SQL statement. A question mark
?
value in this string indicates the position of the varying parameters (the IN-List). Thepos
argument indicates which column of the SQL ResultSet should be used to construct the returned Set object.- Parameters:
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.- Returns:
- A Set of the results of the query..
-
execute
Deprecated.since 8.0; useexecuteSet(String,int,Object...)
insteadExecute the query based on the current elements.The query text must be a valid SQL statement. The substring
IN(?)
in this string indicates the position of the varying parameters (the IN-List). Thepos
argument indicates which column of the SQL ResultSet should be used to construct the returned Map object.- Parameters:
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.bindVars
- if the condition contains place holders for binding variables this parameter list should contain the values- Returns:
- A Map of the results of the query..
-
executeSet
Execute the query based on the current elements.The query text must be a valid SQL statement. The substring
IN(?)
in this string indicates the position of the varying parameters (the IN-List). Thepos
argument indicates which column of the SQL ResultSet should be used to construct the returned Set object.- Parameters:
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.bindVars
- if the condition contains place holders for binding variables this parameter list should contain the values- Returns:
- A Set of the results of the query..
-
execute
Execute the condition based on the current elements.The condition text must be a valid SQL condition statement (without keyword 'where'). A question mark
?
value in this string indicates the position of the varying parameters (the IN-List). Thec
argument indicates on which persistent object the condition should be applied- Parameters:
c
- the class which instances are wanted as the result (c must implementPersistentObject
)condition
- the condition for filtering within the instances.- Returns:
- A list of instances of the passed class which match the specified condition
-
execute
Execute the condition based on the current elements.The condition text must be a valid SQL condition statement (without keyword 'where'). The substring
IN(?)
in this string indicates the position of the varying parameters (the IN-List). Thec
argument indicates on which persistent object the condition should be applied- Parameters:
c
- the class which instances are wanted as the result (c must implementPersistentObject
)condition
- the condition for filtering within the instances.bindVars
- if the condition contains place holders for binding variables this parameter list should contain the values- Returns:
- A list of instances of the passed class which match the specified condition
-
execute2
Execute the query based on the current elements.The query text must be a valid SQL query. A question mark
?
value in this string indicates the position of the varying parameters (the IN-List). Thec
argument indicates on which persistent object the query should be applied- Parameters:
c
- the class which instances are wanted as the result (c must implementPersistentObject
)q
- a SQL query like inStore.list2(Class, String, Object...)
- Returns:
- A list of instances of the passed class which match the specified condition
-
execute2
Execute the query based on the current elements.The query text must be a valid SQL query. The substring
IN(?)
in this string indicates the position of the varying parameters (the IN-List). Thec
argument indicates on which persistent object the query should be applied- Parameters:
c
- the class which instances are wanted as the result (c must implementPersistentObject
)q
- a SQL query like inStore.list2(Class, String, Object...)
bindVars
- if the query contains place holders for binding variables this parameter list should contain the values- Returns:
- A list of instances of the passed class which match the specified condition
-
count
Count the number of members of a given class matching the given condition based on the current elements.The condition text must be a valid SQL condition statement (without keyword 'where'). The substring
IN(?)
in this string indicates the position of the varying parameters (the IN-List). Thec
argument indicates on which persistent object the query should be applied- Parameters:
c
- the class which instances are counted (c must implementPersistentObject
)condition
- a SQL condition like inStore.count(Class, String, Object...)
bindVars
- if the condition contains place holders for binding variables this parameter list should contain the values- Returns:
- The number of instances of the passed class which match the specified condition
-
executeSet(String,int)
instead