|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object tribble.sql.SqlTypeQuery<ResultType>
public class SqlTypeQuery<ResultType>
SQL query builder. Uses a JDBC connection to query an SQL database, then stores the results of the query into an object of a class type (ResultType) provided by the client.
Note:
This class is intended to replace class SqlObjectQuery
, using Java
generics instead of the nonspecific Object type. Likewise, the
query result class SqlObjectResultSet
is replaced by class
SqlTypeResultSet
.
Usage
Our client has a JDBC connection to a database:
Connection conn; Statement stmt; // Establish the JDBC connection conn = driverManager.getConnection(...); stmt = conn.createStatement(...);
The following SQL query is to be performed against the database:
SELECT TOP 100 DISTINCT e.first_name, e.last_name, e.employee_id, w.salary_per_year FROM employees e JOIN employee_wages w ON w.employee_id = e.employee_id WHERE e.last_name BETWEEN 'R' AND 'S' ORDER BY e.last_name
Each row of the result of this query is to be assigned to an object of type EmployeeInfo:
public class EmployeeInfo { public EmployeeInfo() { ... } public void setId(int id) { ... } public void setFirstName(String name) { ... } public void setLastName(String name) { ... } public void setSalary(double amt) { ... } ... }
Note that the EmployeeInfo result type must be public, and have public setter methods and/or public member variables.
We construct a SqlTypeQuery
object and provide it with the
connection and the query. Note that the SELECT keyword of the query
is omitted; we provide any options follwing the implied SELECT
keyword by calling addSelect()
, and we provide the selected
column names by calling addField()
. The rest of the query,
starting with the FROM clause, is provided by calling
addClause()
:
SqlTypeQuery<EmployeeInfo> req = null; // Build the SQL query and result object mapping req = newSqlTypeQuery
<MyObject>(); req.addSelect
("TOP 100"); req.addSelect("DISTINCT"); req.addField
("e.employee_id", "setId()"); req.addField("e.first_name", "setFirstName()"); req.addField("e.last_name", "setLastName()"); req.addField("w.salary_per_year", "setSalary()"); req.addClause
("FROM employees e"); req.addClause("JOIN employee_wages w ON w.employee_id = e.employee_id"); req.addClause("WHERE e.last_name BETWEEN 'R' AND 'S'"); req.addClause("ORDER BY e.last_name"); // e.employee_id will be set by EmployeeInfo.setId() // e.first_name will be set by EmployeeInfo.setFirstName() // e.last_name will be set by EmployeeInfo.setLastName() // w.salary_per_year will be set by EmployeeInfo.setSalary()
Each invocation of addField() assigns a field (column) of the SQL query result to either a class setter method or a class member variable in the result object type. The first argument specifies the text of the field to be included in the SQL query string. The second argument specifies the name of either a setter method (by ending with "()") or the name of a member variable. In either case, the named member must be public. Java reflection is used to locate the specified class member. (Note that setting a member variable directly is generally considered bad object-oriented programming style, the use of a setter method being considered safer, but such capability is included here for completeness.)
If a query field is needed for the query string itself but the value is not used in the result object (such as a field used for a GROUP BY clause), null is passed as the second argument. The field will be included in the SQL query string, but the resulting value for it will be ignored.
Note that the order of the invocations to addField() is important; the first call assigns the result of column 1, the second call assigns the result of column 2, and so forth. This means that calls to addSelect() must not specify additional query fields; otherwise, the resulting SQL query result member assignments will not behave as expected.
Once the query has been set up, it is then executed:
SqlTypeResultSet
<EmployeeInfo> rset = null; try { // Execute the SQL query rset = req.executeQuery
(stmt); } catch (SQLException ex) { // Failure System.out.println("SQL query failed"); throw ex; } finally { // Clean up if (rset != null) rset.close
(); if (req != null) req.close
(); if (stmt != null) stmt.close(); }
The results of the query (zero or more rows) can then be retrieved in a way similar to the way results are obtained from a JDBC ResultSet, one row at a time:
// Retrieve the results of the SQL query while (rset.next()) { EmployeeInfo row; // Get the next result row as an object row = rset.getResult
(); // e.employee_id is set by row.setId() // e.first_name is set by row.setFirstName() // e.last_name is set by row.setLastName() // w.salary_per_year is set by row.setSalary() System.out.println("Employee: " + row.getFirstName() + " " + row.getLastName()); System.out.println(" ID #" + row.getId() + ": $" + row.getSalary()); } // Clean up rset.close
(); req.close
(); stmt.close();
The call to getResult() instantiates a new result object, in this case of type EmployeeInfo, and populates its members from the query result according to the order in which the addField() calls were made above. The result is a single object containing members whose values are retrieved from columns of a row of the query result.
For increased efficiency, caching of the result class information can be
enabled. This causes information about the result class type to be stored in
a local cache each time an SqlTypeQuery object is instantiated.
This can speed up processing if the same result class types are used multiple
times. Caching is disabled by default, but can be enabled by calling
enableCaching()
. Information about a specific result
class can also be cached explicitly by calling cacheInfo()
.
Note that the cache is static, so it is shared by all SqlTypeQuery
instances within the same JVM.
Note: This requires Java 1.5 or later.
Copyright ©2008 by David R. Tribble, all rights reserved.
Permission is granted to any person or entity except those designated by
by the United States Department of State as a terrorist, or terrorist
government or agency, to use and distribute this source code provided
that the original copyright notice remains present and unaltered.
Field Summary | |
---|---|
(package private) static java.lang.String |
REV
|
Constructor Summary | |
---|---|
SqlTypeQuery(java.lang.Class resultType)
Constructor. |
Method Summary | |
---|---|
void |
addClause(java.lang.String clause)
Add a trailing clause to the SQL query. |
void |
addField(java.lang.String field,
java.lang.String member)
Add a field expression to the SELECT clause of the SQL query. |
void |
addSelect(java.lang.String clause)
Add a leading clause to the SELECT clause of the SQL query. |
void |
cacheInfo()
Save information about the result type class in a local cache. |
void |
close()
Shut down this query object. |
static boolean |
enableCaching(boolean flag)
Enable or disable caching of result type class information. |
SqlTypeResultSet<ResultType> |
executeQuery(java.sql.Statement stmt)
Execute the SQL query. |
java.lang.String |
getQueryString()
Retrieve the SQL query string to be executed. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
static final java.lang.String REV
Constructor Detail |
---|
public SqlTypeQuery(java.lang.Class resultType) throws java.sql.SQLException
resultType
- Class type of the result of the SQL query.
Each row of the result set will be converted into an object of this type.
java.sql.SQLException
- Thrown if the result class type is not public or is abstract, or does not
have a public default (no-args) constructor.Method Detail |
---|
public static boolean enableCaching(boolean flag)
flag
- If true, information about result type classes is cached, otherwise
caching is disabled.
The cache is static, so it is shared by all SqlTypeQuery
instances within the same JVM.
cacheInfo()
public void cacheInfo()
Note that this method operates regardless of any previous settings made by
calling enableCaching()
.
enableCaching()
public void addField(java.lang.String field, java.lang.String member) throws java.sql.SQLException
A specified SQL field expression (e.g., "employees.employee_id
as eid") is included as part of the SQL query to be
executed by executeQuery()
. It is paired with a
specific member of the ResultType class. The specified member is
either the name of a member variable (e.g., "employeeID") or the
name of a setter method (e.g., "setEmployeeID()"). In either
case, the type of the SQL field must be assignable to the member variable
or be passable as the single argument of the setter method.
The Java types supported are:
field
- The column name as it appears in the SELECT clause of the SQL
query (e.g., "e.employee_id"). The name can also include an
alias clause (e.g., "e.employee_id id") to be used in the rest of
the SQL query.
member
- The name of the member variable or setter method of the
ResultType class that the field is to be assigned to when the
query result object is retrieved. If the name ends with "()", it
specifies a setter method to be called to assign the result value;
otherwise it specifies a member variable to be assigned.
The name can be null, in which case the column name will not be assigned
to any member of class ResultType (presumably this specifies a
column or expression that is used in a GROUP BY clause.)
java.sql.SQLException
- Thrown if var does not name a member variable or method of the
result type class, or if the named member is not of one of the supported
types.public void addSelect(java.lang.String clause) throws java.sql.SQLException
For reference, a standard SQL query looks like this:
SELECT [option...] column [alias] [, ...] FROM table [alias] [ JOIN table [alias] ON expr ] [ WHERE expr ] [ ORDER BY expr [, ...] ] [ GROUP BY expr [, ...] [ HAVING expr ] ]
Note that this method should only be called once on a given query object.
java.sql.SQLException
- Thrown if executeQuery()
,
getQueryString()
, or close()
has been invoked.public void addClause(java.lang.String clause) throws java.sql.SQLException
For reference, a standard SQL query looks like this:
SELECT [clause...] column [[AS] alias] [, ...] FROM table [alias] [ JOIN table [alias] ON expr ] [ WHERE expr ] [ ORDER BY expr [, ...] ] [ GROUP BY expr [, ...] [ HAVING expr ] ]
java.sql.SQLException
- Thrown if executeQuery()
,
getQueryString()
, or close()
has been invoked.public java.lang.String getQueryString()
Note that once this method has been called, the query cannot be modified
any further by calling addSelect()
,
addField()
, or addClause()
; doing so
will cause an exception to be thrown.
public SqlTypeResultSet<ResultType> executeQuery(java.sql.Statement stmt) throws java.sql.SQLException
SqlTypeResultSet.getResult()
.
Note that once this method has been called, the query cannot be modified
any further by calling addSelect()
,
addField()
, or addClause()
; doing so
will cause an exception to be thrown.
Note also that the query object can be reused, calling its
executeQuery()
method multiple times to get multiple
result sets.
stmt
- A JDBC statement with which to execute the SQL query.
java.sql.SQLException
- Thrown if an error occurs while executing the SQL query.public void close()
executeQuery()
result in exceptions.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |