Add support for parameterized queries to Table &c.
Then fix up UserRepository to not concatenate strings. Good lord. 25 years ago MDB was too lazy.
This commit is contained in:
@@ -12,16 +12,16 @@ import com.samskivert.io.PersistenceException;
|
|||||||
import com.samskivert.jdbc.jora.*;
|
import com.samskivert.jdbc.jora.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JORA repository simplifies the process of building persistence
|
* The JORA repository simplifies the process of building persistence services that make use of the
|
||||||
* services that make use of the JORA object relational mapping package.
|
* JORA object relational mapping package.
|
||||||
*
|
*
|
||||||
* @see com.samskivert.jdbc.jora.Table
|
* @see com.samskivert.jdbc.jora.Table
|
||||||
*/
|
*/
|
||||||
public abstract class JORARepository extends SimpleRepository
|
public abstract class JORARepository extends SimpleRepository
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates and initializes a JORA repository which will access the
|
* Creates and initializes a JORA repository which will access the database identified by the
|
||||||
* database identified by the supplied database identifier.
|
* supplied database identifier.
|
||||||
*
|
*
|
||||||
* @param provider the connection provider which will be used to
|
* @param provider the connection provider which will be used to
|
||||||
* obtain our database connection.
|
* obtain our database connection.
|
||||||
@@ -73,13 +73,12 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates fields specified by the supplied field mask in the supplied
|
* Updates fields specified by the supplied field mask in the supplied object in the specified
|
||||||
* object in the specified table.
|
* table.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by the update.
|
* @return the number of rows modified by the update.
|
||||||
*/
|
*/
|
||||||
protected <T> int update (final Table<T> table, final T object,
|
protected <T> int update (final Table<T> table, final T object, final FieldMask mask)
|
||||||
final FieldMask mask)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return executeUpdate(new Operation<Integer>() {
|
return executeUpdate(new Operation<Integer>() {
|
||||||
@@ -92,16 +91,13 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all objects from the specified table that match the supplied
|
* Loads all objects from the specified table that match the supplied query.
|
||||||
* query.
|
|
||||||
*/
|
*/
|
||||||
protected <T> ArrayList<T> loadAll (final Table<T> table,
|
protected <T> ArrayList<T> loadAll (final Table<T> table, final String query)
|
||||||
final String query)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<ArrayList<T>>() {
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
public ArrayList<T> invoke (
|
public ArrayList<T> invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.select(conn, query).toArrayList();
|
return table.select(conn, query).toArrayList();
|
||||||
@@ -110,16 +106,34 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all objects from the specified table that match the supplied
|
* Loads all objects from the specified table that match the supplied parameterized query.
|
||||||
* query, joining with the supplied auxiliary table(s).
|
*
|
||||||
|
* @param query a WHERE clause using ? placeholders for parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
*/
|
*/
|
||||||
protected <T> ArrayList<T> loadAll (
|
protected <T> ArrayList<T> loadAllParams (final Table<T> table, final String query,
|
||||||
final Table<T> table, final String auxtable, final String query)
|
final Object... params)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<ArrayList<T>>() {
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
public ArrayList<T> invoke (
|
public ArrayList<T> invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
Connection conn, DatabaseLiaison liaison)
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.selectParams(conn, query, params).toArrayList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all objects from the specified table that match the supplied query, joining with the
|
||||||
|
* supplied auxiliary table(s).
|
||||||
|
*/
|
||||||
|
protected <T> ArrayList<T> loadAll (final Table<T> table, final String auxtable,
|
||||||
|
final String query)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
|
public ArrayList<T> invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.select(conn, auxtable, query).toArrayList();
|
return table.select(conn, auxtable, query).toArrayList();
|
||||||
@@ -128,16 +142,13 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all objects from the specified table that match the supplied
|
* Loads all objects from the specified table that match the supplied example.
|
||||||
* example.
|
|
||||||
*/
|
*/
|
||||||
protected <T> ArrayList<T> loadAllByExample (
|
protected <T> ArrayList<T> loadAllByExample (final Table<T> table, final T example)
|
||||||
final Table<T> table, final T example)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<ArrayList<T>>() {
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
public ArrayList<T> invoke (
|
public ArrayList<T> invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.queryByExample(conn, example).toArrayList();
|
return table.queryByExample(conn, example).toArrayList();
|
||||||
@@ -146,16 +157,14 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all objects from the specified table that match the supplied
|
* Loads all objects from the specified table that match the supplied example.
|
||||||
* example.
|
|
||||||
*/
|
*/
|
||||||
protected <T> ArrayList<T> loadAllByExample (
|
protected <T> ArrayList<T> loadAllByExample (
|
||||||
final Table<T> table, final T example, final FieldMask mask)
|
final Table<T> table, final T example, final FieldMask mask)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<ArrayList<T>>() {
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
public ArrayList<T> invoke (
|
public ArrayList<T> invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.queryByExample(conn, example, mask).toArrayList();
|
return table.queryByExample(conn, example, mask).toArrayList();
|
||||||
@@ -164,9 +173,8 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a single object from the specified table that matches the
|
* Loads a single object from the specified table that matches the supplied query.
|
||||||
* supplied query. <em>Note:</em> the query should match one or zero
|
* <em>Note:</em> the query should match one or zero records, not more.
|
||||||
* records, not more.
|
|
||||||
*/
|
*/
|
||||||
protected <T> T load (final Table<T> table, final String query)
|
protected <T> T load (final Table<T> table, final String query)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
@@ -181,12 +189,30 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a single object from the specified table that matches the supplied
|
* Loads a single object from the specified table that matches the supplied parameterized query.
|
||||||
* query, joining with the supplied auxiliary table(s). <em>Note:</em> the
|
* <em>Note:</em> the query should match one or zero records, not more.
|
||||||
* query should match one or zero records, not more.
|
*
|
||||||
|
* @param query a WHERE clause using ? placeholders for parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
*/
|
*/
|
||||||
protected <T> T load (
|
protected <T> T loadParams (final Table<T> table, final String query, final Object... params)
|
||||||
final Table<T> table, final String auxtable, final String query)
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<T>() {
|
||||||
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.selectParams(conn, query, params).get();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a single object from the specified table that matches the supplied query, joining with
|
||||||
|
* the supplied auxiliary table(s). <em>Note:</em> the query should match one or zero records,
|
||||||
|
* not more.
|
||||||
|
*/
|
||||||
|
protected <T> T load (final Table<T> table, final String auxtable, final String query)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<T>() {
|
return execute(new Operation<T>() {
|
||||||
@@ -199,9 +225,29 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a single object from the specified table that matches the
|
* Loads a single object from the specified table that matches the supplied parameterized query,
|
||||||
* supplied example. <em>Note:</em> the query should match one or zero
|
* joining with the supplied auxiliary table(s). <em>Note:</em> the query should match one or
|
||||||
* records, not more.
|
* zero records, not more.
|
||||||
|
*
|
||||||
|
* @param query a WHERE clause using ? placeholders for parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
|
*/
|
||||||
|
protected <T> T loadParams (final Table<T> table, final String auxtable, final String query,
|
||||||
|
final Object... params)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<T>() {
|
||||||
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.selectParams(conn, auxtable, query, params).get();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a single object from the specified table that matches the supplied example.
|
||||||
|
* <em>Note:</em> the query should match one or zero records, not more.
|
||||||
*/
|
*/
|
||||||
protected <T> T loadByExample (final Table<T> table, final T example)
|
protected <T> T loadByExample (final Table<T> table, final T example)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
@@ -216,12 +262,10 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a single object from the specified table that matches the
|
* Loads a single object from the specified table that matches the supplied example.
|
||||||
* supplied example. <em>Note:</em> the query should match one or zero
|
* <em>Note:</em> the query should match one or zero records, not more.
|
||||||
* records, not more.
|
|
||||||
*/
|
*/
|
||||||
protected <T> T loadByExample (
|
protected <T> T loadByExample (final Table<T> table, final T example, final FieldMask mask)
|
||||||
final Table<T> table, final T example, final FieldMask mask)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<T>() {
|
return execute(new Operation<T>() {
|
||||||
@@ -234,9 +278,9 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First attempts to update the supplied object and if that modifies
|
* First attempts to update the supplied object and if that modifies zero rows, inserts the
|
||||||
* zero rows, inserts the object into the specified table. The table
|
* object into the specified table. The table must be configured to store items of the supplied
|
||||||
* must be configured to store items of the supplied type.
|
* type.
|
||||||
*
|
*
|
||||||
* @return -1 if the object was updated, the last inserted id if it was
|
* @return -1 if the object was updated, the last inserted id if it was
|
||||||
* inserted.
|
* inserted.
|
||||||
@@ -258,13 +302,12 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified field in the supplied object (which must
|
* Updates the specified field in the supplied object (which must correspond to the supplied
|
||||||
* correspond to the supplied table).
|
* table).
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by the update.
|
* @return the number of rows modified by the update.
|
||||||
*/
|
*/
|
||||||
protected <T> int updateField (
|
protected <T> int updateField (final Table<T> table, final T object, String field)
|
||||||
final Table<T> table, final T object, String field)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
final FieldMask mask = table.getFieldMask();
|
final FieldMask mask = table.getFieldMask();
|
||||||
@@ -279,13 +322,12 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified fields in the supplied object (which must
|
* Updates the specified fields in the supplied object (which must correspond to the supplied
|
||||||
* correspond to the supplied table).
|
* table).
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by the update.
|
* @return the number of rows modified by the update.
|
||||||
*/
|
*/
|
||||||
protected <T> int updateFields (
|
protected <T> int updateFields (final Table<T> table, final T object, String[] fields)
|
||||||
final Table<T> table, final T object, String[] fields)
|
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
final FieldMask mask = table.getFieldMask();
|
final FieldMask mask = table.getFieldMask();
|
||||||
|
|||||||
@@ -266,6 +266,34 @@ public class SimpleRepository extends Repository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the supplied parameterized update query in this repository, returning the number of
|
||||||
|
* rows modified.
|
||||||
|
*
|
||||||
|
* @param query the SQL update/insert/delete statement with ? placeholders.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
|
*/
|
||||||
|
protected int updateParams (final String query, final Object... params)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return executeUpdate(new Operation<Integer>() {
|
||||||
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
PreparedStatement stmt = null;
|
||||||
|
try {
|
||||||
|
stmt = conn.prepareStatement(query);
|
||||||
|
for (int ii = 0; ii < params.length; ii++) {
|
||||||
|
stmt.setObject(ii + 1, params[ii]);
|
||||||
|
}
|
||||||
|
return stmt.executeUpdate();
|
||||||
|
} finally {
|
||||||
|
JDBCUtil.close(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the supplied update query in this repository, throwing an exception if the
|
* Executes the supplied update query in this repository, throwing an exception if the
|
||||||
* modification count is not equal to the specified count.
|
* modification count is not equal to the specified count.
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ public class Cursor<V>
|
|||||||
_table.bindQueryVariables(qbeStmt, _qbeObject, _qbeMask);
|
_table.bindQueryVariables(qbeStmt, _qbeObject, _qbeMask);
|
||||||
_result = qbeStmt.executeQuery();
|
_result = qbeStmt.executeQuery();
|
||||||
_stmt = qbeStmt;
|
_stmt = qbeStmt;
|
||||||
|
} else if (_params != null) {
|
||||||
|
PreparedStatement pstmt = _conn.prepareStatement(_query);
|
||||||
|
for (int ii = 0; ii < _params.length; ii++) {
|
||||||
|
pstmt.setObject(ii + 1, _params[ii]);
|
||||||
|
}
|
||||||
|
_result = pstmt.executeQuery();
|
||||||
|
_stmt = pstmt;
|
||||||
} else {
|
} else {
|
||||||
if (_stmt == null) {
|
if (_stmt == null) {
|
||||||
_stmt = _conn.createStatement();
|
_stmt = _conn.createStatement();
|
||||||
@@ -194,8 +201,15 @@ public class Cursor<V>
|
|||||||
_query = query;
|
_query = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Cursor (Table<V> table, Connection conn, V obj,
|
protected Cursor (Table<V> table, Connection conn, String query, Object[] params)
|
||||||
FieldMask mask, boolean like)
|
{
|
||||||
|
_table = table;
|
||||||
|
_conn = conn;
|
||||||
|
_query = query;
|
||||||
|
_params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Cursor (Table<V> table, Connection conn, V obj, FieldMask mask, boolean like)
|
||||||
{
|
{
|
||||||
_table = table;
|
_table = table;
|
||||||
_conn = conn;
|
_conn = conn;
|
||||||
@@ -213,6 +227,7 @@ public class Cursor<V>
|
|||||||
protected Statement _stmt;
|
protected Statement _stmt;
|
||||||
protected V _currObject, _qbeObject;
|
protected V _currObject, _qbeObject;
|
||||||
protected FieldMask _qbeMask;
|
protected FieldMask _qbeMask;
|
||||||
|
protected Object[] _params;
|
||||||
protected boolean _like;
|
protected boolean _like;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import com.samskivert.util.StringUtil;
|
|||||||
public class Table<T>
|
public class Table<T>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Constructor for table object. Make association between Java class and
|
* Constructor for table object. Make association between Java class and database table.
|
||||||
* database table.
|
|
||||||
*
|
*
|
||||||
* @param clazz the class that represents a row entry.
|
* @param clazz the class that represents a row entry.
|
||||||
* @param tableName name of database table mapped on this Java class
|
* @param tableName name of database table mapped on this Java class
|
||||||
@@ -30,16 +29,14 @@ public class Table<T>
|
|||||||
* @param mixedCaseConvert whether or not to convert mixed case field
|
* @param mixedCaseConvert whether or not to convert mixed case field
|
||||||
* names into underscore separated uppercase column names.
|
* names into underscore separated uppercase column names.
|
||||||
*/
|
*/
|
||||||
public Table (Class<T> clazz, String tableName, String key,
|
public Table (Class<T> clazz, String tableName, String key, boolean mixedCaseConvert)
|
||||||
boolean mixedCaseConvert)
|
|
||||||
{
|
{
|
||||||
String[] keys = {key};
|
String[] keys = {key};
|
||||||
init(clazz, tableName, keys, mixedCaseConvert);
|
init(clazz, tableName, keys, mixedCaseConvert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for table object. Make association between Java class and
|
* Constructor for table object. Make association between Java class and database table.
|
||||||
* database table.
|
|
||||||
*
|
*
|
||||||
* @param clazz the class that represents a row entry.
|
* @param clazz the class that represents a row entry.
|
||||||
* @param tableName name of database table mapped on this Java class
|
* @param tableName name of database table mapped on this Java class
|
||||||
@@ -52,8 +49,7 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for table object. Make association between Java class and
|
* Constructor for table object. Make association between Java class and database table.
|
||||||
* database table.
|
|
||||||
*
|
*
|
||||||
* @param clazz the class that represents a row entry.
|
* @param clazz the class that represents a row entry.
|
||||||
* @param tableName name of database table mapped on this Java class
|
* @param tableName name of database table mapped on this Java class
|
||||||
@@ -66,8 +62,7 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for table object. Make association between Java class and
|
* Constructor for table object. Make association between Java class and database table.
|
||||||
* database table.
|
|
||||||
*
|
*
|
||||||
* @param clazz the class that represents a row entry.
|
* @param clazz the class that represents a row entry.
|
||||||
* @param tableName name of database table mapped on this Java class
|
* @param tableName name of database table mapped on this Java class
|
||||||
@@ -76,8 +71,7 @@ public class Table<T>
|
|||||||
* @param mixedCaseConvert whether or not to convert mixed case field
|
* @param mixedCaseConvert whether or not to convert mixed case field
|
||||||
* names into underscore separated uppercase column names.
|
* names into underscore separated uppercase column names.
|
||||||
*/
|
*/
|
||||||
public Table (Class<T> clazz, String tableName, String[] keys,
|
public Table (Class<T> clazz, String tableName, String[] keys, boolean mixedCaseConvert)
|
||||||
boolean mixedCaseConvert)
|
|
||||||
{
|
{
|
||||||
init(clazz, tableName, keys, mixedCaseConvert);
|
init(clazz, tableName, keys, mixedCaseConvert);
|
||||||
}
|
}
|
||||||
@@ -98,64 +92,85 @@ public class Table<T>
|
|||||||
*/
|
*/
|
||||||
public final Cursor<T> select (Connection conn, String condition)
|
public final Cursor<T> select (Connection conn, String condition)
|
||||||
{
|
{
|
||||||
String query = "select " + listOfFields + " from " + name +
|
String query = "select " + listOfFields + " from " + name + " " + condition;
|
||||||
|
return new Cursor<T>(this, conn, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select records from database table according to search condition using a parameterized query.
|
||||||
|
*
|
||||||
|
* @param condition valid SQL condition expression started with WHERE, using ? placeholders for
|
||||||
|
* parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
|
*/
|
||||||
|
public final Cursor<T> selectParams (Connection conn, String condition, Object... params)
|
||||||
|
{
|
||||||
|
String query = "select " + listOfFields + " from " + name + " " + condition;
|
||||||
|
return new Cursor<T>(this, conn, query, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select records from database table according to search condition including the specified
|
||||||
|
* (comma separated) extra tables into the SELECT clause to facilitate a join in determining the
|
||||||
|
* key, using a parameterized query.
|
||||||
|
*
|
||||||
|
* @param tables the (comma separated) names of extra tables to include in the SELECT clause.
|
||||||
|
* @param condition valid SQL condition expression started with WHERE, using ? placeholders for
|
||||||
|
* parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
|
*/
|
||||||
|
public final Cursor<T> selectParams (Connection conn, String tables, String condition,
|
||||||
|
Object... params)
|
||||||
|
{
|
||||||
|
String query = "select " + qualifiedListOfFields + " from " + name + "," + tables +
|
||||||
|
" " + condition;
|
||||||
|
return new Cursor<T>(this, conn, query, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select records from database table according to search condition including the specified
|
||||||
|
* (comma separated) extra tables into the SELECT clause to facilitate a join in determining the
|
||||||
|
* key.
|
||||||
|
*
|
||||||
|
* @param tables the (comma separated) names of extra tables to include in the SELECT clause.
|
||||||
|
* @param condition valid SQL condition expression started with WHERE.
|
||||||
|
*/
|
||||||
|
public final Cursor<T> select (Connection conn, String tables, String condition)
|
||||||
|
{
|
||||||
|
String query = "select " + qualifiedListOfFields + " from " + name + "," + tables +
|
||||||
" " + condition;
|
" " + condition;
|
||||||
return new Cursor<T>(this, conn, query);
|
return new Cursor<T>(this, conn, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select records from database table according to search condition
|
* Select records from database table according to search condition including the specified
|
||||||
* including the specified (comma separated) extra tables into the SELECT
|
* (comma separated) extra tables into the SELECT clause to facilitate a join in determining the
|
||||||
* clause to facilitate a join in determining the key.
|
* key. To facilitate situations where data from multiple tables is being combined into a single
|
||||||
|
* object, the fields will not be qualified with the primary table name.
|
||||||
*
|
*
|
||||||
* @param tables the (comma separated) names of extra tables to include in
|
* @param tables the (comma separated) names of extra tables to include in the SELECT clause.
|
||||||
* the SELECT clause.
|
|
||||||
* @param condition valid SQL condition expression started with WHERE.
|
* @param condition valid SQL condition expression started with WHERE.
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> select (Connection conn, String tables,
|
public final Cursor<T> join (Connection conn, String tables, String condition)
|
||||||
String condition)
|
|
||||||
{
|
{
|
||||||
String query = "select " + qualifiedListOfFields +
|
String query = "select " + listOfFields + " from " + name + "," + tables + " " + condition;
|
||||||
" from " + name + "," + tables + " " + condition;
|
|
||||||
return new Cursor<T>(this, conn, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select records from database table according to search condition
|
|
||||||
* including the specified (comma separated) extra tables into the SELECT
|
|
||||||
* clause to facilitate a join in determining the key. To facilitate
|
|
||||||
* situations where data from multiple tables is being combined into a
|
|
||||||
* single object, the fields will not be qualified with the primary table
|
|
||||||
* name.
|
|
||||||
*
|
|
||||||
* @param tables the (comma separated) names of extra tables to include in
|
|
||||||
* the SELECT clause.
|
|
||||||
* @param condition valid SQL condition expression started with WHERE.
|
|
||||||
*/
|
|
||||||
public final Cursor<T> join (Connection conn, String tables,
|
|
||||||
String condition)
|
|
||||||
{
|
|
||||||
String query = "select " + listOfFields +
|
|
||||||
" from " + name + "," + tables + " " + condition;
|
|
||||||
return new Cursor<T>(this, conn, query);
|
return new Cursor<T>(this, conn, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #join} but does a straight join with the specified table.
|
* Like {@link #join} but does a straight join with the specified table.
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> straightJoin (Connection conn, String table,
|
public final Cursor<T> straightJoin (Connection conn, String table, String condition)
|
||||||
String condition)
|
|
||||||
{
|
{
|
||||||
String query = "select " + listOfFields +
|
String query = "select " + listOfFields + " from " + name + " straight_join " + table +
|
||||||
" from " + name + " straight_join " + table + " " + condition;
|
" " + condition;
|
||||||
return new Cursor<T>(this, conn, query);
|
return new Cursor<T>(this, conn, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select records from database table using <I>obj</I> object as template.
|
* Select records from database table using <I>obj</I> object as template.
|
||||||
*
|
*
|
||||||
* @param obj example object for search: selected objects should match all
|
* @param obj example object for search: selected objects should match all non-null fields.
|
||||||
* non-null fields.
|
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> queryByExample (Connection conn, T obj)
|
public final Cursor<T> queryByExample (Connection conn, T obj)
|
||||||
{
|
{
|
||||||
@@ -163,23 +178,20 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select records from database table using <I>obj</I> object as template
|
* Select records from database table using <I>obj</I> object as template for selection.
|
||||||
* for selection.
|
|
||||||
*
|
*
|
||||||
* @param obj example object for search.
|
* @param obj example object for search.
|
||||||
* @param mask field mask indicating which fields in the example object
|
* @param mask field mask indicating which fields in the example object should be used when
|
||||||
* should be used when building the query.
|
* building the query.
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> queryByExample (Connection conn, T obj,
|
public final Cursor<T> queryByExample (Connection conn, T obj, FieldMask mask)
|
||||||
FieldMask mask)
|
|
||||||
{
|
{
|
||||||
return new Cursor<T>(this, conn, obj, mask, false);
|
return new Cursor<T>(this, conn, obj, mask, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as the queryByExample, but string fields for the obj are
|
* The same as the queryByExample, but string fields for the obj are matched using 'like'
|
||||||
* matched using 'like' instead of equals, which allows you to send % in to
|
* instead of equals, which allows you to send % in to do matching.
|
||||||
* do matching.
|
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> queryByLikeExample (Connection conn, T obj)
|
public final Cursor<T> queryByLikeExample (Connection conn, T obj)
|
||||||
{
|
{
|
||||||
@@ -187,19 +199,17 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as the queryByExample, but string fields for the obj are
|
* The same as the queryByExample, but string fields for the obj are matched using 'like'
|
||||||
* matched using 'like' instead of equals, which allows you to send % in to
|
* instead of equals, which allows you to send % in to do matching.
|
||||||
* do matching.
|
|
||||||
*/
|
*/
|
||||||
public final Cursor<T> queryByLikeExample (Connection conn, T obj,
|
public final Cursor<T> queryByLikeExample (Connection conn, T obj, FieldMask mask)
|
||||||
FieldMask mask)
|
|
||||||
{
|
{
|
||||||
return new Cursor<T>(this, conn, obj, mask, true);
|
return new Cursor<T>(this, conn, obj, mask, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert new record in the table. Values of inserted record fields are
|
* Insert new record in the table. Values of inserted record fields are taken from specified
|
||||||
* taken from specified object.
|
* object.
|
||||||
*
|
*
|
||||||
* @param obj object specifying values of inserted record fields
|
* @param obj object specifying values of inserted record fields
|
||||||
*/
|
*/
|
||||||
@@ -253,11 +263,10 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert several new records in the table. Values of inserted records
|
* Insert several new records in the table. Values of inserted records fields are taken from
|
||||||
* fields are taken from objects of specified array.
|
* objects of specified array.
|
||||||
*
|
*
|
||||||
* @param objects array with objects specifying values of inserted record
|
* @param objects array with objects specifying values of inserted record fields
|
||||||
* fields
|
|
||||||
*/
|
*/
|
||||||
public synchronized void insert (Connection conn, T[] objects)
|
public synchronized void insert (Connection conn, T[] objects)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
@@ -278,8 +287,8 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a field mask that can be configured and used to update subsets
|
* Returns a field mask that can be configured and used to update subsets of entire objects via
|
||||||
* of entire objects via calls to {@link #update(Connection,Object,FieldMask)}.
|
* calls to {@link #update(Connection,Object,FieldMask)}.
|
||||||
*/
|
*/
|
||||||
public FieldMask getFieldMask ()
|
public FieldMask getFieldMask ()
|
||||||
{
|
{
|
||||||
@@ -287,12 +296,10 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update record in the table using table's primary key to locate record in
|
* Update record in the table using table's primary key to locate record in the table and values
|
||||||
* the table and values of fields of specified object <I>obj</I> to alter
|
* of fields of specified object <I>obj</I> to alter record fields.
|
||||||
* record fields.
|
|
||||||
*
|
*
|
||||||
* @param obj object specifying value of primary key and new values of
|
* @param obj object specifying value of primary key and new values of updated record fields
|
||||||
* updated record fields
|
|
||||||
*
|
*
|
||||||
* @return number of objects actually updated
|
* @return number of objects actually updated
|
||||||
*/
|
*/
|
||||||
@@ -303,15 +310,13 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update record in the table using table's primary key to locate record in
|
* Update record in the table using table's primary key to locate record in the table and values
|
||||||
* the table and values of fields of specified object <I>obj</I> to alter
|
* of fields of specified object <I>obj</I> to alter record fields. Only the fields marked as
|
||||||
* record fields. Only the fields marked as modified in the supplied field
|
* modified in the supplied field mask will be updated in the database.
|
||||||
* mask will be updated in the database.
|
|
||||||
*
|
*
|
||||||
* @param obj object specifying value of primary key and new values of
|
* @param obj object specifying value of primary key and new values of updated record fields
|
||||||
* updated record fields
|
* @param mask a {@link FieldMask} instance configured to indicate which of the object's fields
|
||||||
* @param mask a {@link FieldMask} instance configured to indicate which of
|
* are modified and should be written to the database.
|
||||||
* the object's fields are modified and should be written to the database.
|
|
||||||
*
|
*
|
||||||
* @return number of objects actually updated
|
* @return number of objects actually updated
|
||||||
*/
|
*/
|
||||||
@@ -334,12 +339,11 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update set of records in the table using table's primary key to locate
|
* Update set of records in the table using table's primary key to locate record in the table
|
||||||
* record in the table and values of fields of objects from specified array
|
* and values of fields of objects from specified array <I>objects</I> to alter record fields.
|
||||||
* <I>objects</I> to alter record fields.
|
|
||||||
*
|
*
|
||||||
* @param objects array of objects specifying primary keys and and new
|
* @param objects array of objects specifying primary keys and and new values of updated record
|
||||||
* values of updated record fields
|
* fields
|
||||||
*
|
*
|
||||||
* @return number of objects actually updated
|
* @return number of objects actually updated
|
||||||
*/
|
*/
|
||||||
@@ -352,15 +356,13 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nUpdated = 0;
|
int nUpdated = 0;
|
||||||
String sql = "update " + name + " set " + listOfAssignments +
|
String sql = "update " + name + " set " + listOfAssignments + buildUpdateWhere();
|
||||||
buildUpdateWhere();
|
|
||||||
PreparedStatement updateStmt = conn.prepareStatement(sql);
|
PreparedStatement updateStmt = conn.prepareStatement(sql);
|
||||||
for (int i = 0; i < objects.length; i++) {
|
for (int i = 0; i < objects.length; i++) {
|
||||||
int column = bindUpdateVariables(updateStmt, objects[i], null);
|
int column = bindUpdateVariables(updateStmt, objects[i], null);
|
||||||
for (int j = 0; j < primaryKeys.length; j++) {
|
for (int j = 0; j < primaryKeys.length; j++) {
|
||||||
int fidx = primaryKeyIndices[j];
|
int fidx = primaryKeyIndices[j];
|
||||||
fields[fidx].bindVariable(
|
fields[fidx].bindVariable(updateStmt, objects[i], column+1+j);
|
||||||
updateStmt, objects[i], column+1+j);
|
|
||||||
}
|
}
|
||||||
updateStmt.addBatch();
|
updateStmt.addBatch();
|
||||||
}
|
}
|
||||||
@@ -381,8 +383,7 @@ public class Table<T>
|
|||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (primaryKeys == null) {
|
if (primaryKeys == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("No primary key for table " + name + ".");
|
||||||
"No primary key for table " + name + ".");
|
|
||||||
}
|
}
|
||||||
int nDeleted = 0;
|
int nDeleted = 0;
|
||||||
StringBuilder sql = new StringBuilder(
|
StringBuilder sql = new StringBuilder(
|
||||||
@@ -410,8 +411,7 @@ public class Table<T>
|
|||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (primaryKeys == null) {
|
if (primaryKeys == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("No primary key for table " + name + ".");
|
||||||
"No primary key for table " + name + ".");
|
|
||||||
}
|
}
|
||||||
int nDeleted = 0;
|
int nDeleted = 0;
|
||||||
StringBuilder sql = new StringBuilder(
|
StringBuilder sql = new StringBuilder(
|
||||||
@@ -422,8 +422,7 @@ public class Table<T>
|
|||||||
PreparedStatement deleteStmt = conn.prepareStatement(sql.toString());
|
PreparedStatement deleteStmt = conn.prepareStatement(sql.toString());
|
||||||
for (int i = 0; i < objects.length; i++) {
|
for (int i = 0; i < objects.length; i++) {
|
||||||
for (int j = 0; j < primaryKeys.length; j++) {
|
for (int j = 0; j < primaryKeys.length; j++) {
|
||||||
fields[primaryKeyIndices[j]].bindVariable(
|
fields[primaryKeyIndices[j]].bindVariable(deleteStmt, objects[i], j+1);
|
||||||
deleteStmt, objects[i], j+1);
|
|
||||||
}
|
}
|
||||||
deleteStmt.addBatch();
|
deleteStmt.addBatch();
|
||||||
}
|
}
|
||||||
@@ -438,15 +437,13 @@ public class Table<T>
|
|||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[name=" + name +
|
return "[name=" + name + ", primaryKeys=" + StringUtil.toString(primaryKeys) + "]";
|
||||||
", primaryKeys=" + StringUtil.toString(primaryKeys) + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Separator of name components of compound field. For example, if Java
|
* Separator of name components of compound field. For example, if Java class contains component
|
||||||
* class contains component "location" of Point class, which has two
|
* "location" of Point class, which has two components "x" and "y", then database table should
|
||||||
* components "x" and "y", then database table should have columns
|
* have columns "location_x" and "location_y" (if '_' is used as separator).
|
||||||
* "location_x" and "location_y" (if '_' is used as separator).
|
|
||||||
*/
|
*/
|
||||||
public static final String fieldSeparator = "_";
|
public static final String fieldSeparator = "_";
|
||||||
|
|
||||||
@@ -460,8 +457,7 @@ public class Table<T>
|
|||||||
listOfFields = "";
|
listOfFields = "";
|
||||||
qualifiedListOfFields = "";
|
qualifiedListOfFields = "";
|
||||||
listOfAssignments = "";
|
listOfAssignments = "";
|
||||||
ArrayList<FieldDescriptor> fieldsVector =
|
ArrayList<FieldDescriptor> fieldsVector = new ArrayList<FieldDescriptor>();
|
||||||
new ArrayList<FieldDescriptor>();
|
|
||||||
nFields = buildFieldsList(fieldsVector, _rowClass, "");
|
nFields = buildFieldsList(fieldsVector, _rowClass, "");
|
||||||
fields = fieldsVector.toArray(new FieldDescriptor[nFields]);
|
fields = fieldsVector.toArray(new FieldDescriptor[nFields]);
|
||||||
fMask = new FieldMask(fields);
|
fMask = new FieldMask(fields);
|
||||||
@@ -478,16 +474,14 @@ public class Table<T>
|
|||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
if (fields[i].name.equals(keys[j])) {
|
if (fields[i].name.equals(keys[j])) {
|
||||||
if (!fields[i].isAtomic()) {
|
if (!fields[i].isAtomic()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Non-atomic primary key provided");
|
||||||
"Non-atomic primary key provided");
|
|
||||||
}
|
}
|
||||||
primaryKeyIndices[j] = i;
|
primaryKeyIndices[j] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
throw new NoSuchFieldError("No such field '" + keys[j]
|
throw new NoSuchFieldError("No such field '" + keys[j] + "' in table " + name);
|
||||||
+ "' in table " + name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,8 +496,8 @@ public class Table<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int buildFieldsList (ArrayList<FieldDescriptor> buf,
|
protected final int buildFieldsList (ArrayList<FieldDescriptor> buf, Class<?> _rowClass,
|
||||||
Class<?> _rowClass, String prefix)
|
String prefix)
|
||||||
{
|
{
|
||||||
Field[] f = _rowClass.getDeclaredFields();
|
Field[] f = _rowClass.getDeclaredFields();
|
||||||
|
|
||||||
@@ -511,8 +505,7 @@ public class Table<T>
|
|||||||
while ((superclass = superclass.getSuperclass()) != null) {
|
while ((superclass = superclass.getSuperclass()) != null) {
|
||||||
Field[] inheritedFields = superclass.getDeclaredFields();
|
Field[] inheritedFields = superclass.getDeclaredFields();
|
||||||
Field[] allFields = new Field[inheritedFields.length + f.length];
|
Field[] allFields = new Field[inheritedFields.length + f.length];
|
||||||
System.arraycopy(inheritedFields, 0, allFields, 0,
|
System.arraycopy(inheritedFields, 0, allFields, 0, inheritedFields.length);
|
||||||
inheritedFields.length);
|
|
||||||
System.arraycopy(f,0, allFields, inheritedFields.length, f.length);
|
System.arraycopy(f,0, allFields, inheritedFields.length, f.length);
|
||||||
f = allFields;
|
f = allFields;
|
||||||
}
|
}
|
||||||
@@ -529,8 +522,7 @@ public class Table<T>
|
|||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (int i = 0; i < f.length; i++) {
|
for (int i = 0; i < f.length; i++) {
|
||||||
if ((f[i].getModifiers()&(Modifier.TRANSIENT|Modifier.STATIC))==0)
|
if ((f[i].getModifiers()&(Modifier.TRANSIENT|Modifier.STATIC))==0) {
|
||||||
{
|
|
||||||
String name = f[i].getName();
|
String name = f[i].getName();
|
||||||
Class<?> fieldClass = f[i].getType();
|
Class<?> fieldClass = f[i].getType();
|
||||||
String fullName = prefix + convertName(name);
|
String fullName = prefix + convertName(name);
|
||||||
@@ -548,49 +540,29 @@ public class Table<T>
|
|||||||
else if (c.equals("float")) type = FieldDescriptor.t_float;
|
else if (c.equals("float")) type = FieldDescriptor.t_float;
|
||||||
else if (c.equals("double")) type = FieldDescriptor.t_double;
|
else if (c.equals("double")) type = FieldDescriptor.t_double;
|
||||||
else if (c.equals("boolean")) type = FieldDescriptor.t_boolean;
|
else if (c.equals("boolean")) type = FieldDescriptor.t_boolean;
|
||||||
else if (c.equals("java.lang.Byte"))
|
else if (c.equals("java.lang.Byte")) type = FieldDescriptor.tByte;
|
||||||
type = FieldDescriptor.tByte;
|
else if (c.equals("java.lang.Short")) type = FieldDescriptor.tShort;
|
||||||
else if (c.equals("java.lang.Short"))
|
else if (c.equals("java.lang.Integer")) type = FieldDescriptor.tInteger;
|
||||||
type = FieldDescriptor.tShort;
|
else if (c.equals("java.lang.Long")) type = FieldDescriptor.tLong;
|
||||||
else if (c.equals("java.lang.Integer"))
|
else if (c.equals("java.lang.Float")) type = FieldDescriptor.tFloat;
|
||||||
type = FieldDescriptor.tInteger;
|
else if (c.equals("java.lang.Double")) type = FieldDescriptor.tDouble;
|
||||||
else if (c.equals("java.lang.Long"))
|
else if (c.equals("java.lang.Boolean")) type = FieldDescriptor.tBoolean;
|
||||||
type = FieldDescriptor.tLong;
|
else if (c.equals("java.math.BigDecimal")) type = FieldDescriptor.tDecimal;
|
||||||
else if (c.equals("java.lang.Float"))
|
else if (c.equals("java.lang.String")) type = FieldDescriptor.tString;
|
||||||
type = FieldDescriptor.tFloat;
|
else if (fieldClass.equals(BYTE_PROTO.getClass())) type = FieldDescriptor.tBytes;
|
||||||
else if (c.equals("java.lang.Double"))
|
else if (c.equals("java.sql.Date")) type = FieldDescriptor.tDate;
|
||||||
type = FieldDescriptor.tDouble;
|
else if (c.equals("java.sql.Time")) type = FieldDescriptor.tTime;
|
||||||
else if (c.equals("java.lang.Boolean"))
|
else if (c.equals("java.sql.Timestamp")) type = FieldDescriptor.tTimestamp;
|
||||||
type = FieldDescriptor.tBoolean;
|
else if (c.equals("java.lang.InputStream")) type = FieldDescriptor.tStream;
|
||||||
else if (c.equals("java.math.BigDecimal"))
|
else if (c.equals("java.sql.BlobLocator")) type = FieldDescriptor.tBlob;
|
||||||
type = FieldDescriptor.tDecimal;
|
else if (c.equals("java.sql.ClobLocator")) type = FieldDescriptor.tClob;
|
||||||
else if (c.equals("java.lang.String"))
|
else if (serializableClass.isAssignableFrom(fieldClass)) type = FieldDescriptor.tClosure;
|
||||||
type = FieldDescriptor.tString;
|
|
||||||
else if (fieldClass.equals(BYTE_PROTO.getClass()))
|
|
||||||
type = FieldDescriptor.tBytes;
|
|
||||||
else if (c.equals("java.sql.Date"))
|
|
||||||
type = FieldDescriptor.tDate;
|
|
||||||
else if (c.equals("java.sql.Time"))
|
|
||||||
type = FieldDescriptor.tTime;
|
|
||||||
else if (c.equals("java.sql.Timestamp"))
|
|
||||||
type = FieldDescriptor.tTimestamp;
|
|
||||||
else if (c.equals("java.lang.InputStream"))
|
|
||||||
type = FieldDescriptor.tStream;
|
|
||||||
else if (c.equals("java.sql.BlobLocator"))
|
|
||||||
type = FieldDescriptor.tBlob;
|
|
||||||
else if (c.equals("java.sql.ClobLocator"))
|
|
||||||
type = FieldDescriptor.tClob;
|
|
||||||
else if (serializableClass.isAssignableFrom(fieldClass))
|
|
||||||
type = FieldDescriptor.tClosure;
|
|
||||||
else {
|
else {
|
||||||
int nComponents = buildFieldsList(buf, fieldClass,
|
int nComponents = buildFieldsList(buf, fieldClass, fd.name+fieldSeparator);
|
||||||
fd.name+fieldSeparator);
|
fd.inType = fd.outType = FieldDescriptor.tCompound + nComponents;
|
||||||
fd.inType = fd.outType =
|
|
||||||
FieldDescriptor.tCompound + nComponents;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fd.constructor =
|
fd.constructor = fieldClass.getDeclaredConstructor(new Class<?>[0]);
|
||||||
fieldClass.getDeclaredConstructor(new Class<?>[0]);
|
|
||||||
setBypass.invoke(fd.constructor, bypassFlag);
|
setBypass.invoke(fd.constructor, bypassFlag);
|
||||||
} catch(Exception ex) {}
|
} catch(Exception ex) {}
|
||||||
|
|
||||||
@@ -647,20 +619,17 @@ public class Table<T>
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int load (
|
protected final int load (Object obj, int i, int end, int column, ResultSet result)
|
||||||
Object obj, int i, int end, int column, ResultSet result)
|
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
while (i < end) {
|
while (i < end) {
|
||||||
FieldDescriptor fd = fields[i++];
|
FieldDescriptor fd = fields[i++];
|
||||||
if (!fd.loadVariable(result, obj, ++column)) {
|
if (!fd.loadVariable(result, obj, ++column)) {
|
||||||
Object component =
|
Object component = fd.constructor.newInstance(constructorArgs);
|
||||||
fd.constructor.newInstance(constructorArgs);
|
|
||||||
fd.field.set(obj, component);
|
fd.field.set(obj, component);
|
||||||
int nComponents = fd.inType - FieldDescriptor.tCompound;
|
int nComponents = fd.inType - FieldDescriptor.tCompound;
|
||||||
column = load(component, i, i + nComponents,
|
column = load(component, i, i + nComponents, column-1, result);
|
||||||
column-1, result);
|
|
||||||
i += nComponents;
|
i += nComponents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -673,17 +642,13 @@ public class Table<T>
|
|||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int bindUpdateVariables(PreparedStatement pstmt,
|
protected final int bindUpdateVariables(PreparedStatement pstmt, T obj, FieldMask mask)
|
||||||
T obj,
|
|
||||||
FieldMask mask)
|
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
return bindUpdateVariables(pstmt, obj, 0, nFields, 0, mask);
|
return bindUpdateVariables(pstmt, obj, 0, nFields, 0, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void bindQueryVariables(PreparedStatement pstmt,
|
protected final void bindQueryVariables(PreparedStatement pstmt, T obj, FieldMask mask)
|
||||||
T obj,
|
|
||||||
FieldMask mask)
|
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
bindQueryVariables(pstmt, obj, 0, nFields, 0, mask);
|
bindQueryVariables(pstmt, obj, 0, nFields, 0, mask);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package com.samskivert.servlet.user;
|
|||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
@@ -86,7 +87,7 @@ public class UserRepository extends JORARepository
|
|||||||
public User loadUser (String username)
|
public User loadUser (String username)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return loadUserWhere("where username = " + JDBCUtil.escape(username));
|
return loadUserWhereParams("where username = ?", username);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,8 +110,9 @@ public class UserRepository extends JORARepository
|
|||||||
public User loadUserBySession (String sessionKey)
|
public User loadUserBySession (String sessionKey)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
User user = load(_utable, "sessions", "where authcode = '" + sessionKey + "' " +
|
User user = loadParams(_utable, "sessions",
|
||||||
"AND sessions.userId = users.userId");
|
"where authcode = ? AND sessions.userId = users.userId",
|
||||||
|
sessionKey);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.setDirtyMask(_utable.getFieldMask());
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
}
|
}
|
||||||
@@ -145,7 +147,7 @@ public class UserRepository extends JORARepository
|
|||||||
public ArrayList<User> lookupUsersByEmail (String email)
|
public ArrayList<User> lookupUsersByEmail (String email)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return loadAll(_utable, "where email = " + JDBCUtil.escape(email));
|
return loadAllParams(_utable, "where email = ?", email);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -251,14 +253,16 @@ public class UserRepository extends JORARepository
|
|||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
// look for an existing session for this user
|
// look for an existing session for this user
|
||||||
final String query = "select authcode from sessions where userId = " + user.userId;
|
final int userId = user.userId;
|
||||||
String authcode = execute(new Operation<String>() {
|
String authcode = execute(new Operation<String>() {
|
||||||
public String invoke (Connection conn, DatabaseLiaison liaison)
|
public String invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws PersistenceException, SQLException
|
throws PersistenceException, SQLException
|
||||||
{
|
{
|
||||||
Statement stmt = conn.createStatement();
|
PreparedStatement stmt = conn.prepareStatement(
|
||||||
|
"select authcode from sessions where userId = ?");
|
||||||
try {
|
try {
|
||||||
ResultSet rs = stmt.executeQuery(query);
|
stmt.setInt(1, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
return rs.getString(1);
|
return rs.getString(1);
|
||||||
}
|
}
|
||||||
@@ -276,13 +280,12 @@ public class UserRepository extends JORARepository
|
|||||||
|
|
||||||
// if we found one, update its expires time and reuse it
|
// if we found one, update its expires time and reuse it
|
||||||
if (authcode != null) {
|
if (authcode != null) {
|
||||||
update("update sessions set expires = '" + expires + "' where " +
|
updateParams("update sessions set expires = ? where authcode = ?", expires, authcode);
|
||||||
"authcode = '" + authcode + "'");
|
|
||||||
} else {
|
} else {
|
||||||
// otherwise create a new one and insert it into the table
|
// otherwise create a new one and insert it into the table
|
||||||
authcode = UserUtil.genAuthCode(user);
|
authcode = UserUtil.genAuthCode(user);
|
||||||
update("insert into sessions (authcode, userId, expires) values('" + authcode + "', " +
|
updateParams("insert into sessions (authcode, userId, expires) values(?, ?, ?)",
|
||||||
user.userId + ", '" + expires + "')");
|
authcode, user.userId, expires);
|
||||||
}
|
}
|
||||||
|
|
||||||
return authcode;
|
return authcode;
|
||||||
@@ -302,8 +305,8 @@ public class UserRepository extends JORARepository
|
|||||||
Date expires = new Date(cal.getTime().getTime());
|
Date expires = new Date(cal.getTime().getTime());
|
||||||
|
|
||||||
// attempt to update an existing session row, returning true if we found and updated it
|
// attempt to update an existing session row, returning true if we found and updated it
|
||||||
return (update("update sessions set expires = '" + expires + "' " +
|
return (updateParams("update sessions set expires = ? where authcode = ?",
|
||||||
"where authcode = " + JDBCUtil.escape(sessionKey)) == 1);
|
expires, sessionKey) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -429,6 +432,23 @@ public class UserRepository extends JORARepository
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads up a user record that matches the specified parameterized where clause. Returns null
|
||||||
|
* if no record matches.
|
||||||
|
*
|
||||||
|
* @param where a WHERE clause using ? placeholders for parameters.
|
||||||
|
* @param params parameter values to bind to the ? placeholders.
|
||||||
|
*/
|
||||||
|
protected User loadUserWhereParams (String where, Object... params)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
User user = loadParams(_utable, where, params);
|
||||||
|
if (user != null) {
|
||||||
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
protected String[] loadNames (int[] userIds, final String column)
|
protected String[] loadNames (int[] userIds, final String column)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user