public class BulkQuery extends Object
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:
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(?).
Modifier and Type | Field and Description |
---|---|
static String |
IN
Marker for the in-List in the BulkQuery
|
Constructor and Description |
---|
BulkQuery()
Construct a fresh BulkQuery.
|
BulkQuery(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.
|
BulkQuery(int splitSize)
Construct a fresh BulkQuery and set a split size
|
Modifier and Type | Method and Description |
---|---|
void |
add(Collection<?> c,
boolean isSplitted)
Add the elements of the Collection to a BulkQuery.
|
void |
add(long l)
Add a long to the query.
|
void |
add(Long l)
Add a Long to the query.
|
void |
add(Persistent p)
Add the oid of a Persistent to the query.
|
void |
add(String s)
Add a String to the query.
|
void |
addQuoted(String s)
Add a String to the query.
|
int |
count(Class<?> c,
String condition,
Object... bindVars)
Count the number of members of a given class matching the given condition based on the current elements.
|
<T> List<T> |
execute(Class<? extends T> c,
String condition)
Execute the condition based on the current elements.
|
<T> List<T> |
execute(Class<? extends T> c,
String condition,
Object... bindVars)
Execute the condition based on the current elements.
|
Map<Object,Object> |
execute(String query,
int pos)
Deprecated.
since 8.0; use
executeSet(String,int) instead |
Map<Object,Object> |
execute(String query,
int pos,
Object... bindVars)
Deprecated.
since 8.0; use
executeSet(String,int,Object...) instead |
<P> List<P> |
execute2(Class<? extends P> c,
String q)
Execute the query based on the current elements.
|
<P> List<P> |
execute2(Class<? extends P> c,
String q,
Object... bindVars)
Execute the query based on the current elements.
|
Set<String> |
executeSet(String query,
int pos)
Execute the query based on the current elements.
|
Set<String> |
executeSet(String query,
int pos,
Object... bindVars)
Execute the query based on the current elements.
|
int |
getSplitSize() |
int |
setSplitSize(int splitSize) |
public static final String IN
public BulkQuery()
public BulkQuery(int splitSize)
public BulkQuery(Collection<?> c)
String
objects, Long
objects or implement the
Persistent
interface.c
- the Collection whose elements are added to the BulkQuery.public BulkQuery(Collection<?> c, boolean isSplitted)
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 like BulkQuery(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 than getSplitSize()
values, else the query might fail.public void add(Collection<?> c, boolean isSplitted)
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 like BulkQuery(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 than getSplitSize()
values, else the query might fail.public void add(String s)
s
- the String to be added.public void addQuoted(String s)
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.
public void add(Persistent p)
p
- the Persistent, which oid is to be added.public void add(Long l)
l
- the Long to be added.public void add(long l)
l
- the long to be added.public int getSplitSize()
public int setSplitSize(int splitSize)
@Deprecated public Map<Object,Object> execute(String query, int pos)
executeSet(String,int)
instead
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).
The pos
argument indicates which column of the SQL ResultSet should be used to construct
the returned Map object.
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.public Set<String> executeSet(String query, int pos)
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).
The pos
argument indicates which column of the SQL ResultSet should be used to construct
the returned Set object.
query
- The query text.pos
- The position in the queries ResultSet which should be used for construction of the result.@Deprecated public Map<Object,Object> execute(String query, int pos, Object... bindVars)
executeSet(String,int,Object...)
instead
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).
The pos
argument indicates which column of the SQL ResultSet should be used to construct
the returned Map object.
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 valuespublic Set<String> executeSet(String query, int pos, Object... bindVars)
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).
The pos
argument indicates which column of the SQL ResultSet should be used to construct
the returned Set object.
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 valuespublic <T> List<T> execute(Class<? extends T> c, String condition)
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).
The c
argument indicates on which persistent object the condition should
be applied
c
- the class which instances are wanted as the result (c must implement PersistentObject
)condition
- the condition for filtering within the instances.public <T> List<T> execute(Class<? extends T> c, String condition, Object... bindVars)
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).
The c
argument indicates on which persistent object the condition should
be applied
c
- the class which instances are wanted as the result (c must implement PersistentObject
)condition
- the condition for filtering within the instances.bindVars
- if the condition contains place holders for binding variables this parameter list should contain the valuespublic <P> List<P> execute2(Class<? extends P> c, String q)
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).
The c
argument indicates on which persistent object the query should
be applied
c
- the class which instances are wanted as the result (c must implement PersistentObject
)q
- a SQL query like in Store.list2(Class, String, Object...)
public <P> List<P> execute2(Class<? extends P> c, String q, Object... bindVars)
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).
The c
argument indicates on which persistent object the query should
be applied
c
- the class which instances are wanted as the result (c must implement PersistentObject
)q
- a SQL query like in Store.list2(Class, String, Object...)
bindVars
- if the query contains place holders for binding variables this parameter list should contain the valuespublic int count(Class<?> c, String condition, Object... bindVars)
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).
The c
argument indicates on which persistent object the query should
be applied
c
- the class which instances are counted (c must implement PersistentObject
)condition
- a SQL condition like in Store.count(Class, String, Object...)
bindVars
- if the condition contains place holders for binding variables this parameter list should contain the values@enterprise 10.0.39049 Copyright © 2024 FREQUENTIS AG. All Rights Reserved.