Modifications to clone() on insertion and extraction from cache, from Zell. A
whole bunch of type safety jockeying and concretification of QueryClause by yours truly.
This commit is contained in:
@@ -65,7 +65,7 @@ public abstract class ConstructedQuery<T>
|
||||
*
|
||||
* This method is called by individual clauses.
|
||||
*/
|
||||
public String getTableAbbreviation (Class cl)
|
||||
public String getTableAbbreviation (Class<? extends PersistentRecord> cl)
|
||||
{
|
||||
int ix = _classList.indexOf(cl);
|
||||
if (ix < 0) {
|
||||
@@ -197,11 +197,13 @@ public abstract class ConstructedQuery<T>
|
||||
* class, as dictated by the key and query clauses. A persistence context is supplied for
|
||||
* instantiation of marshallers, which may trigger table creations and schema migrations.
|
||||
*/
|
||||
protected ConstructedQuery (PersistenceContext ctx, Class type, QueryClause... clauses)
|
||||
protected ConstructedQuery (PersistenceContext ctx, Class<? extends PersistentRecord> type,
|
||||
QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
_mainType = type;
|
||||
Set<Class> classSet = new HashSet<Class>();
|
||||
Set<Class<? extends PersistentRecord>> classSet =
|
||||
new HashSet<Class<? extends PersistentRecord>>();
|
||||
if (type != null) {
|
||||
classSet.add(type);
|
||||
}
|
||||
@@ -261,17 +263,17 @@ public abstract class ConstructedQuery<T>
|
||||
}
|
||||
_classMap = new HashMap<Class, DepotMarshaller>();
|
||||
|
||||
for (Class<?> c : classSet) {
|
||||
for (Class<? extends PersistentRecord> c : classSet) {
|
||||
_classMap.put(c, ctx.getMarshaller(c));
|
||||
}
|
||||
_classList = new ArrayList<Class>(classSet);
|
||||
_classList = new ArrayList<Class<? extends PersistentRecord>>(classSet);
|
||||
}
|
||||
|
||||
/** The persistent class to instantiate for the results. */
|
||||
protected Class _mainType;
|
||||
protected Class<? extends PersistentRecord> _mainType;
|
||||
|
||||
/** A list of referenced classes, used to generate table abbreviations. */
|
||||
protected List<Class> _classList;
|
||||
protected List<Class<? extends PersistentRecord>> _classList;
|
||||
|
||||
/** Classes mapped to marshallers, used for table names and field lists. */
|
||||
protected Map<Class, DepotMarshaller> _classMap;
|
||||
|
||||
@@ -63,7 +63,7 @@ import static com.samskivert.jdbc.depot.Log.log;
|
||||
* Handles the marshalling and unmarshalling of persistent instances to JDBC primitives ({@link
|
||||
* PreparedStatement} and {@link ResultSet}).
|
||||
*/
|
||||
public class DepotMarshaller<T>
|
||||
public class DepotMarshaller<T extends PersistentRecord>
|
||||
{
|
||||
/** The name of a private static field that must be defined for all persistent object classes.
|
||||
* It is used to handle schema migration. If automatic schema migration is not desired, define
|
||||
|
||||
@@ -29,9 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.jdbc.ConnectionProvider;
|
||||
import com.samskivert.jdbc.JDBCUtil;
|
||||
@@ -66,7 +63,8 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads the persistent object that matches the specified primary key.
|
||||
*/
|
||||
protected <T> T load (Class<T> type, Comparable primaryKey, QueryClause... clauses)
|
||||
protected <T extends PersistentRecord> T load (Class<T> type, Comparable primaryKey,
|
||||
QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
clauses = ArrayUtil.append(clauses, _ctx.getMarshaller(type).makePrimaryKey(primaryKey));
|
||||
@@ -76,7 +74,8 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads the persistent object that matches the specified primary key.
|
||||
*/
|
||||
protected <T> T load (Class<T> type, String ix, Comparable val, QueryClause... clauses)
|
||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix, Comparable val,
|
||||
QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
clauses = ArrayUtil.append(clauses, new Key<T>(type, ix, val));
|
||||
@@ -86,8 +85,9 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads the persistent object that matches the specified two-column primary key.
|
||||
*/
|
||||
protected <T> T load (Class<T> type, String ix1, Comparable val1, String ix2,
|
||||
Comparable val2, QueryClause... clauses)
|
||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix1, Comparable val1,
|
||||
String ix2, Comparable val2,
|
||||
QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
clauses = ArrayUtil.append(clauses, new Key<T>(type, ix1, val1, ix2, val2));
|
||||
@@ -97,8 +97,9 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads the persistent object that matches the specified three-column primary key.
|
||||
*/
|
||||
protected <T> T load (Class<T> type, String ix1, Comparable val1, String ix2,
|
||||
Comparable val2, String ix3, Comparable val3, QueryClause... clauses)
|
||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix1, Comparable val1,
|
||||
String ix2, Comparable val2, String ix3,
|
||||
Comparable val3, QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
clauses = ArrayUtil.append(clauses, new Key<T>(type, ix1, val1, ix2, val2, ix3, val3));
|
||||
@@ -108,7 +109,7 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads the first persistent object that matches the supplied key.
|
||||
*/
|
||||
protected <T> T load (Class<T> type, QueryClause... clauses)
|
||||
protected <T extends PersistentRecord> T load (Class<T> type, QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller<T> marsh = _ctx.getMarshaller(type);
|
||||
@@ -130,6 +131,7 @@ public class DepotRepository
|
||||
}
|
||||
}
|
||||
|
||||
// from Query
|
||||
public void updateCache (PersistenceContext ctx, T result) {
|
||||
CacheKey key = getCacheKey();
|
||||
if (key == null) {
|
||||
@@ -140,7 +142,18 @@ public class DepotRepository
|
||||
// if we can, create a key from what was actually returned
|
||||
key = marsh.getPrimaryKey(result);
|
||||
}
|
||||
ctx.cacheStore(key, result);
|
||||
ctx.cacheStore(key, result != null ? result.clone() : null);
|
||||
}
|
||||
|
||||
// from Query
|
||||
public T transformCacheHit (CacheKey key, T value)
|
||||
{
|
||||
// we do not want to return a reference to the actual cached entity
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
@SuppressWarnings("unchecked") T cvalue = (T) value.clone();
|
||||
return cvalue;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -148,7 +161,7 @@ public class DepotRepository
|
||||
/**
|
||||
* Loads all persistent objects that match the specified key.
|
||||
*/
|
||||
protected <T,C extends Collection<T>> Collection<T> findAll (
|
||||
protected <T extends PersistentRecord, C extends Collection<T>> Collection<T> findAll (
|
||||
Class<T> type, QueryClause... clauses)
|
||||
throws PersistenceException
|
||||
{
|
||||
@@ -169,13 +182,33 @@ public class DepotRepository
|
||||
}
|
||||
}
|
||||
|
||||
// from Query
|
||||
public void updateCache (PersistenceContext ctx, ArrayList<T> result) {
|
||||
if (marsh.hasPrimaryKey()) {
|
||||
for (T bit : result) {
|
||||
ctx.cacheStore(marsh.getPrimaryKey(bit), bit);
|
||||
ctx.cacheStore(marsh.getPrimaryKey(bit), bit.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from Query
|
||||
public ArrayList<T> transformCacheHit (CacheKey key, ArrayList<T> bits)
|
||||
{
|
||||
if (bits == null) {
|
||||
return bits;
|
||||
}
|
||||
|
||||
ArrayList<T> result = new ArrayList<T>();
|
||||
for (T bit : bits) {
|
||||
if (bit != null) {
|
||||
@SuppressWarnings("unchecked") T cbit = (T) bit.clone();
|
||||
result.add(cbit);
|
||||
} else {
|
||||
result.add(null);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -185,7 +218,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action, this should always be one.
|
||||
*/
|
||||
protected <T> int insert (final T record)
|
||||
protected <T extends PersistentRecord> int insert (T record)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller marsh = _ctx.getMarshaller(record.getClass());
|
||||
@@ -194,12 +227,12 @@ public class DepotRepository
|
||||
return _ctx.invoke(new CachingModifier<T>(record, key, key) {
|
||||
public int invoke (Connection conn) throws SQLException {
|
||||
// update our modifier's key so that it can cache our results
|
||||
updateKey(marsh.assignPrimaryKey(conn, record, false));
|
||||
PreparedStatement stmt = marsh.createInsert(conn, record);
|
||||
updateKey(marsh.assignPrimaryKey(conn, _result, false));
|
||||
PreparedStatement stmt = marsh.createInsert(conn, _result);
|
||||
try {
|
||||
int mods = stmt.executeUpdate();
|
||||
// check again in case we have a post-factum key generator
|
||||
updateKey(marsh.assignPrimaryKey(conn, record, true));
|
||||
updateKey(marsh.assignPrimaryKey(conn, _result, true));
|
||||
return mods;
|
||||
} finally {
|
||||
JDBCUtil.close(stmt);
|
||||
@@ -214,7 +247,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int update (final T record)
|
||||
protected <T extends PersistentRecord> int update (T record)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller marsh = _ctx.getMarshaller(record.getClass());
|
||||
@@ -224,7 +257,7 @@ public class DepotRepository
|
||||
}
|
||||
return _ctx.invoke(new CachingModifier<T>(record, key, key) {
|
||||
public int invoke (Connection conn) throws SQLException {
|
||||
PreparedStatement stmt = marsh.createUpdate(conn, record, key);
|
||||
PreparedStatement stmt = marsh.createUpdate(conn, _result, key);
|
||||
try {
|
||||
return stmt.executeUpdate();
|
||||
} finally {
|
||||
@@ -240,7 +273,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int update (final T record, final String... modifiedFields)
|
||||
protected <T extends PersistentRecord> int update (T record, final String... modifiedFields)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller marsh = _ctx.getMarshaller(record.getClass());
|
||||
@@ -250,7 +283,7 @@ public class DepotRepository
|
||||
}
|
||||
return _ctx.invoke(new CachingModifier<T>(record, key, key) {
|
||||
public int invoke (Connection conn) throws SQLException {
|
||||
PreparedStatement stmt = marsh.createUpdate(conn, record, key, modifiedFields);
|
||||
PreparedStatement stmt = marsh.createUpdate(conn, _result, key, modifiedFields);
|
||||
try {
|
||||
return stmt.executeUpdate();
|
||||
} finally {
|
||||
@@ -270,8 +303,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int updatePartial (Class<T> type, Comparable primaryKey,
|
||||
Map<String,Object> updates)
|
||||
protected <T extends PersistentRecord> int updatePartial (
|
||||
Class<T> type, Comparable primaryKey, Map<String,Object> updates)
|
||||
throws PersistenceException
|
||||
{
|
||||
Object[] fieldsValues = new Object[updates.size()*2];
|
||||
@@ -293,7 +326,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int updatePartial (Class<T> type, Comparable primaryKey, Object... fieldsValues)
|
||||
protected <T extends PersistentRecord> int updatePartial (
|
||||
Class<T> type, Comparable primaryKey, Object... fieldsValues)
|
||||
throws PersistenceException
|
||||
{
|
||||
Key<T> key = _ctx.getMarshaller(type).makePrimaryKey(primaryKey);
|
||||
@@ -312,8 +346,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int updatePartial (Class<T> type, final Where key, CacheInvalidator invalidator,
|
||||
Object... fieldsValues)
|
||||
protected <T extends PersistentRecord> int updatePartial (
|
||||
Class<T> type, final Where key, CacheInvalidator invalidator, Object... fieldsValues)
|
||||
throws PersistenceException
|
||||
{
|
||||
// separate the arguments into keys and values
|
||||
@@ -354,7 +388,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int updateLiteral (Class<T> type, Comparable primaryKey, String... fieldsValues)
|
||||
protected <T extends PersistentRecord> int updateLiteral (
|
||||
Class<T> type, Comparable primaryKey, String... fieldsValues)
|
||||
throws PersistenceException
|
||||
{
|
||||
Key<T> key = _ctx.getMarshaller(type).makePrimaryKey(primaryKey);
|
||||
@@ -378,8 +413,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action.
|
||||
*/
|
||||
protected <T> int updateLiteral (Class<T> type, final Where key, CacheInvalidator invalidator,
|
||||
String... fieldsValues)
|
||||
protected <T extends PersistentRecord> int updateLiteral (
|
||||
Class<T> type, final Where key, CacheInvalidator invalidator, String... fieldsValues)
|
||||
throws PersistenceException
|
||||
{
|
||||
// separate the arguments into keys and values
|
||||
@@ -410,7 +445,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows modified by this action, this should always be one.
|
||||
*/
|
||||
protected <T> int store (final T record)
|
||||
protected <T extends PersistentRecord> int store (T record)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller marsh = _ctx.getMarshaller(record.getClass());
|
||||
@@ -422,7 +457,7 @@ public class DepotRepository
|
||||
// if our primary key isn't null, update rather than insert the record
|
||||
// before been persisted and insert
|
||||
if (key != null) {
|
||||
stmt = marsh.createUpdate(conn, record, key);
|
||||
stmt = marsh.createUpdate(conn, _result, key);
|
||||
int mods = stmt.executeUpdate();
|
||||
if (mods > 0) {
|
||||
return mods;
|
||||
@@ -432,10 +467,10 @@ public class DepotRepository
|
||||
|
||||
// if the update modified zero rows or the primary key was obviously unset, do
|
||||
// an insertion
|
||||
updateKey(marsh.assignPrimaryKey(conn, record, false));
|
||||
stmt = marsh.createInsert(conn, record);
|
||||
updateKey(marsh.assignPrimaryKey(conn, _result, false));
|
||||
stmt = marsh.createInsert(conn, _result);
|
||||
int mods = stmt.executeUpdate();
|
||||
updateKey(marsh.assignPrimaryKey(conn, record, true));
|
||||
updateKey(marsh.assignPrimaryKey(conn, _result, true));
|
||||
return mods;
|
||||
|
||||
} finally {
|
||||
@@ -451,7 +486,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows deleted by this action.
|
||||
*/
|
||||
protected <T> int delete (T record)
|
||||
protected <T extends PersistentRecord> int delete (T record)
|
||||
throws PersistenceException
|
||||
{
|
||||
@SuppressWarnings("unchecked") Class<T> type = (Class<T>)record.getClass();
|
||||
@@ -468,7 +503,7 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows deleted by this action.
|
||||
*/
|
||||
protected <T> int delete (Class<T> type, Comparable primaryKeyValue)
|
||||
protected <T extends PersistentRecord> int delete (Class<T> type, Comparable primaryKeyValue)
|
||||
throws PersistenceException
|
||||
{
|
||||
Key<T> primaryKey = _ctx.getMarshaller(type).makePrimaryKey(primaryKeyValue);
|
||||
@@ -480,7 +515,8 @@ public class DepotRepository
|
||||
*
|
||||
* @return the number of rows deleted by this action.
|
||||
*/
|
||||
protected <T> int deleteAll (Class<T> type, final Where key, CacheInvalidator invalidator)
|
||||
protected <T extends PersistentRecord> int deleteAll (
|
||||
Class<T> type, final Where key, CacheInvalidator invalidator)
|
||||
throws PersistenceException
|
||||
{
|
||||
final DepotMarshaller marsh = _ctx.getMarshaller(type);
|
||||
|
||||
@@ -23,9 +23,9 @@ package com.samskivert.jdbc.depot;
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.samskivert.jdbc.depot.clause.Where;
|
||||
@@ -37,7 +37,7 @@ import com.samskivert.jdbc.depot.clause.Where;
|
||||
* itself upon modification. This class is created by many {@link DepotMarshaller} methods as
|
||||
* a convenience, and may also be instantiated explicitly.
|
||||
*/
|
||||
public class Key<T> extends Where
|
||||
public class Key<T extends PersistentRecord> extends Where
|
||||
implements CacheKey, CacheInvalidator
|
||||
{
|
||||
/**
|
||||
@@ -94,13 +94,16 @@ public class Key<T> extends Where
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public List<Class> getClassSet()
|
||||
public Collection<Class<? extends PersistentRecord>> getClassSet ()
|
||||
{
|
||||
return Arrays.asList(new Class[] { _pClass });
|
||||
ArrayList<Class<? extends PersistentRecord>> set =
|
||||
new ArrayList<Class<? extends PersistentRecord>>();
|
||||
set.add(_pClass);
|
||||
return set;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" where ");
|
||||
boolean first = true;
|
||||
|
||||
@@ -59,7 +59,7 @@ public abstract class Modifier
|
||||
* presuming both _key and _result are non-null. These variables may be set or modified
|
||||
* during execution in addition to being supplied to the constructor.
|
||||
*/
|
||||
public static abstract class CachingModifier<T> extends Modifier
|
||||
public static abstract class CachingModifier<T extends PersistentRecord> extends Modifier
|
||||
{
|
||||
/**
|
||||
* Construct a new CachingModifier with the given result, cache key, and invalidator,
|
||||
@@ -89,7 +89,7 @@ public abstract class Modifier
|
||||
super.cacheUpdate(ctx);
|
||||
// if we have both a key and a record, cache
|
||||
if (_key != null && _result != null) {
|
||||
ctx.cacheStore(_key, _result);
|
||||
ctx.cacheStore(_key, _result.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ package com.samskivert.jdbc.depot;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.samskivert.jdbc.depot.clause.Where;
|
||||
@@ -34,7 +34,7 @@ import com.samskivert.jdbc.depot.clause.Where;
|
||||
* does not implement {@link CacheKey} but it does implement {@link CacheInvalidator} which means
|
||||
* it can be sent into e.g. {@link DepotRepository#deleteAll) and have it clean up after itself.
|
||||
*/
|
||||
public class MultiKey<T> extends Where
|
||||
public class MultiKey<T extends PersistentRecord> extends Where
|
||||
implements CacheInvalidator
|
||||
{
|
||||
/**
|
||||
@@ -85,13 +85,16 @@ public class MultiKey<T> extends Where
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public List<Class> getClassSet()
|
||||
public Collection<Class<? extends PersistentRecord>> getClassSet ()
|
||||
{
|
||||
return Arrays.asList(new Class[] { _pClass });
|
||||
ArrayList<Class<? extends PersistentRecord>> set =
|
||||
new ArrayList<Class<? extends PersistentRecord>>();
|
||||
set.add(_pClass);
|
||||
return set;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" where ");
|
||||
boolean first = true;
|
||||
|
||||
@@ -140,7 +140,7 @@ public class PersistenceContext
|
||||
* and register a pre-migration for every single schema migration and they will then be
|
||||
* guaranteed to be run in registration order and with predictable pre- and post-conditions.
|
||||
*/
|
||||
public <T> void registerMigration (Class<T> type, EntityMigration migration)
|
||||
public <T extends PersistentRecord> void registerMigration (Class<T> type, EntityMigration migration)
|
||||
{
|
||||
getRawMarshaller(type).registerMigration(migration);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class PersistenceContext
|
||||
* Returns the marshaller for the specified persistent object class, creating and initializing
|
||||
* it if necessary.
|
||||
*/
|
||||
public <T> DepotMarshaller<T> getMarshaller (Class<T> type)
|
||||
public <T extends PersistentRecord> DepotMarshaller<T> getMarshaller (Class<T> type)
|
||||
throws PersistenceException
|
||||
{
|
||||
DepotMarshaller<T> marshaller = getRawMarshaller(type);
|
||||
@@ -176,7 +176,11 @@ public class PersistenceContext
|
||||
if (cacheHit != null) {
|
||||
Log.debug("invoke: cache hit [hit=" + cacheHit + "]");
|
||||
@SuppressWarnings("unchecked") T value = (T) cacheHit.getValue();
|
||||
return value;
|
||||
value = query.transformCacheHit(key, value);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
Log.debug("invoke: transformCacheHit returned null; rejecting cached value.");
|
||||
}
|
||||
}
|
||||
Log.debug("invoke: cache miss [key=" + key + "]");
|
||||
@@ -337,7 +341,7 @@ public class PersistenceContext
|
||||
* Looks up and creates, but does not initialize, the marshaller for the specified Entity
|
||||
* type.
|
||||
*/
|
||||
protected <T> DepotMarshaller<T> getRawMarshaller (Class<T> type)
|
||||
protected <T extends PersistentRecord> DepotMarshaller<T> getRawMarshaller (Class<T> type)
|
||||
{
|
||||
@SuppressWarnings("unchecked") DepotMarshaller<T> marshaller =
|
||||
(DepotMarshaller<T>)_marshallers.get(type);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2007 Michael Bayne, Pär Winzell
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.jdbc.depot;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The base class for all persistent records used in Depot. Persistent records must be cloneable
|
||||
* and serializable; this class is used to enforce those requirements.
|
||||
*/
|
||||
public class PersistentRecord
|
||||
implements Cloneable, Serializable
|
||||
{
|
||||
@Override // from Object
|
||||
public PersistentRecord clone ()
|
||||
{
|
||||
try {
|
||||
return (PersistentRecord) super.clone();
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
throw new RuntimeException(cnse); // this should never happen
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,15 @@ public interface Query<T>
|
||||
*/
|
||||
public T invoke (Connection conn)
|
||||
throws SQLException;
|
||||
|
||||
|
||||
/**
|
||||
* Overriden by subclasses to perform special operations when the query would return a cache
|
||||
* hit. The value may be mutated, modified, or null may be return to force a database hit.
|
||||
*/
|
||||
public T transformCacheHit (CacheKey key, T value);
|
||||
|
||||
/**
|
||||
* Overriden by subclasses to perform case-by-case cache updates.
|
||||
*/
|
||||
void updateCache (PersistenceContext ctx, T result);
|
||||
public void updateCache (PersistenceContext ctx, T result);
|
||||
}
|
||||
|
||||
@@ -20,12 +20,9 @@
|
||||
|
||||
package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.jdbc.depot.expression.ColumnExp;
|
||||
import com.samskivert.jdbc.depot.expression.LiteralExp;
|
||||
import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
@@ -38,8 +35,7 @@ import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
* table through a {@link ColumnExp}, or a literal expression such as COUNT(*) through a
|
||||
* {@link LiteralExp}.
|
||||
*/
|
||||
public class FieldOverride
|
||||
implements QueryClause
|
||||
public class FieldOverride extends QueryClause
|
||||
{
|
||||
public FieldOverride (String field, String str)
|
||||
throws PersistenceException
|
||||
@@ -47,7 +43,7 @@ public class FieldOverride
|
||||
this(field, new LiteralExp(str));
|
||||
}
|
||||
|
||||
public FieldOverride (String field, Class pClass, String pCol)
|
||||
public FieldOverride (String field, Class<? extends PersistentRecord> pClass, String pCol)
|
||||
throws PersistenceException
|
||||
{
|
||||
this(field, new ColumnExp(pClass, pCol));
|
||||
@@ -69,25 +65,12 @@ public class FieldOverride
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
_override.appendExpression(query, builder);
|
||||
builder.append(" as ").append(_field);
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public int bindArguments (PreparedStatement pstmt, int argIdx)
|
||||
throws SQLException
|
||||
{
|
||||
return argIdx;
|
||||
}
|
||||
|
||||
/** The name of the field on the persistent object to override. */
|
||||
protected String _field;
|
||||
|
||||
|
||||
@@ -20,34 +20,16 @@
|
||||
|
||||
package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
|
||||
/**
|
||||
* Represents a FOR UPDATE clause.
|
||||
*/
|
||||
public class ForUpdate
|
||||
implements QueryClause
|
||||
public class ForUpdate extends QueryClause
|
||||
{
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" for update ");
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public int bindArguments (PreparedStatement pstmt, int argIdx)
|
||||
throws SQLException
|
||||
{
|
||||
return argIdx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,53 +20,45 @@
|
||||
|
||||
package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
|
||||
/**
|
||||
* Completely overrides the FROM clause, if it exists.
|
||||
*/
|
||||
public class FromOverride
|
||||
implements QueryClause
|
||||
public class FromOverride extends QueryClause
|
||||
{
|
||||
public FromOverride (Class... fromClasses)
|
||||
public FromOverride (Class<? extends PersistentRecord>... fromClasses)
|
||||
throws PersistenceException
|
||||
{
|
||||
_fromClasses = fromClasses;
|
||||
CollectionUtil.addAll(_fromClasses, fromClasses);
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
public Collection<Class<? extends PersistentRecord>> getClassSet ()
|
||||
{
|
||||
return Arrays.asList(_fromClasses);
|
||||
return _fromClasses;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" from " );
|
||||
for (int ii = 0; ii < _fromClasses.length; ii++) {
|
||||
for (int ii = 0; ii < _fromClasses.size(); ii++) {
|
||||
if (ii > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(query.getTableName(_fromClasses[ii])).
|
||||
append(" as ").
|
||||
append(query.getTableAbbreviation(_fromClasses[ii]));
|
||||
builder.append(query.getTableName(_fromClasses.get(ii))).
|
||||
append(" as ").append(query.getTableAbbreviation(_fromClasses.get(ii)));
|
||||
}
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public int bindArguments (PreparedStatement pstmt, int argIdx)
|
||||
throws SQLException
|
||||
{
|
||||
return argIdx;
|
||||
}
|
||||
|
||||
/** The classes of the tables we're selecting from. */
|
||||
protected Class[] _fromClasses;
|
||||
protected ArrayList<Class<? extends PersistentRecord>> _fromClasses =
|
||||
new ArrayList<Class<? extends PersistentRecord>>();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
@@ -30,8 +29,7 @@ import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
/**
|
||||
* Represents a GROUP BY clause.
|
||||
*/
|
||||
public class GroupBy
|
||||
implements QueryClause
|
||||
public class GroupBy extends QueryClause
|
||||
{
|
||||
public GroupBy (SQLExpression... values)
|
||||
{
|
||||
@@ -39,13 +37,7 @@ public class GroupBy
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" group by ");
|
||||
for (int ii = 0; ii < _values.length; ii++) {
|
||||
|
||||
@@ -22,22 +22,23 @@ package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.jdbc.depot.expression.ColumnExp;
|
||||
import com.samskivert.jdbc.depot.operator.SQLOperator;
|
||||
import com.samskivert.jdbc.depot.operator.Conditionals.*;
|
||||
import com.samskivert.jdbc.depot.operator.SQLOperator;
|
||||
|
||||
/**
|
||||
* Represents a JOIN -- currently just an INNER one.
|
||||
*/
|
||||
public class Join
|
||||
implements QueryClause
|
||||
public class Join extends QueryClause
|
||||
{
|
||||
public Join (Class pClass, String pCol, Class joinClass, String jCol)
|
||||
public Join (Class<? extends PersistentRecord> pClass, String pCol,
|
||||
Class<? extends PersistentRecord> joinClass, String jCol)
|
||||
throws PersistenceException
|
||||
{
|
||||
_joinClass = joinClass;
|
||||
@@ -51,20 +52,23 @@ public class Join
|
||||
_joinCondition = new Equals(primary, join);
|
||||
}
|
||||
|
||||
public Join (Class joinClass, SQLOperator joinCondition)
|
||||
public Join (Class<? extends PersistentRecord> joinClass, SQLOperator joinCondition)
|
||||
{
|
||||
_joinClass = joinClass;
|
||||
_joinCondition = joinCondition;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
public Collection<Class<? extends PersistentRecord>> getClassSet ()
|
||||
{
|
||||
return Arrays.asList(new Class[] { _joinClass });
|
||||
ArrayList<Class<? extends PersistentRecord>> set =
|
||||
new ArrayList<Class<? extends PersistentRecord>>();
|
||||
set.add(_joinClass);
|
||||
return set;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" inner join " );
|
||||
builder.append(query.getTableName(_joinClass)).append(" as ");
|
||||
@@ -80,7 +84,7 @@ public class Join
|
||||
}
|
||||
|
||||
/** The class of the table we're to join against. */
|
||||
protected Class _joinClass;
|
||||
protected Class<? extends PersistentRecord> _joinClass;
|
||||
|
||||
/** The condition used to join in the new table. */
|
||||
protected SQLOperator _joinCondition;
|
||||
|
||||
@@ -22,15 +22,13 @@ package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
|
||||
/**
|
||||
* Represents a LIMIT/OFFSET clause, for pagination.
|
||||
*/
|
||||
public class Limit
|
||||
implements QueryClause
|
||||
public class Limit extends QueryClause
|
||||
{
|
||||
public Limit (int offset, int count)
|
||||
{
|
||||
@@ -39,13 +37,7 @@ public class Limit
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" limit ? offset ? ");
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.expression.ColumnExp;
|
||||
@@ -31,8 +30,7 @@ import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
/**
|
||||
* Represents an ORDER BY clause.
|
||||
*/
|
||||
public class OrderBy
|
||||
implements QueryClause
|
||||
public class OrderBy extends QueryClause
|
||||
{
|
||||
/** Indicates the order of the clause. */
|
||||
public enum Order { ASC, DESC };
|
||||
@@ -76,13 +74,7 @@ public class OrderBy
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public Collection<Class> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" order by ");
|
||||
for (int ii = 0; ii < _values.length; ii++) {
|
||||
|
||||
@@ -25,29 +25,36 @@ import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
|
||||
/**
|
||||
* Represents a piece or modifier of an SQL query.
|
||||
*/
|
||||
public interface QueryClause
|
||||
public abstract class QueryClause
|
||||
{
|
||||
/**
|
||||
* Return a set of all persistent classes referenced by this clause. Null may be returned if
|
||||
* no classes are rererenced.
|
||||
* Return a set of all persistent classes referenced by this clause. The default implementation
|
||||
* returns null to indicate that no classes are rererenced.
|
||||
*/
|
||||
public Collection<Class> getClassSet ();
|
||||
public Collection<Class<? extends PersistentRecord>> getClassSet ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the SQL form of this query clause. The implementor is expected to call methods
|
||||
* on the Query object to e.g. resolve current table abbreviations associated with classes.
|
||||
* Construct the SQL form of this query clause. The implementor is expected to call methods on
|
||||
* the Query object to e.g. resolve current table abbreviations associated with classes.
|
||||
*/
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder);
|
||||
public abstract void appendClause (ConstructedQuery<?> query, StringBuilder builder);
|
||||
|
||||
/**
|
||||
* Bind any objects that were referenced in the generated SQL. For each ? that appears in the
|
||||
* SQL, precisely one parameter must be claimed and bound in this method, and argIdx
|
||||
* incremented and returned.
|
||||
* incremented and returned. The default implementation binds nothing.
|
||||
*/
|
||||
public int bindArguments (PreparedStatement pstmt, int argIdx)
|
||||
throws SQLException;
|
||||
throws SQLException
|
||||
{
|
||||
return argIdx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,24 +22,22 @@ package com.samskivert.jdbc.depot.clause;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.jdbc.depot.clause.QueryClause;
|
||||
import com.samskivert.jdbc.depot.expression.ColumnExp;
|
||||
import com.samskivert.jdbc.depot.expression.ValueExp;
|
||||
import com.samskivert.jdbc.depot.operator.SQLOperator;
|
||||
import com.samskivert.jdbc.depot.operator.Conditionals.Equals;
|
||||
import com.samskivert.jdbc.depot.operator.Conditionals.IsNull;
|
||||
import com.samskivert.jdbc.depot.operator.Logic.And;
|
||||
import com.samskivert.jdbc.depot.operator.SQLOperator;
|
||||
|
||||
/**
|
||||
* Represents a where clause: the condition can be any comparison operator or logical combination
|
||||
* thereof.
|
||||
*/
|
||||
public class Where
|
||||
implements QueryClause
|
||||
public class Where extends QueryClause
|
||||
{
|
||||
public Where (String index, Comparable value)
|
||||
{
|
||||
@@ -88,13 +86,7 @@ public class Where
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public List<Class> getClassSet()
|
||||
{
|
||||
return Arrays.asList(new Class[] { });
|
||||
}
|
||||
|
||||
// from QueryClause
|
||||
public void appendClause (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendClause (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
builder.append(" where ");
|
||||
_condition.appendExpression(query, builder);
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
|
||||
/**
|
||||
* An expression identifying a column of a class, e.g. GameRecord.itemId. If no class is given,
|
||||
@@ -33,7 +34,7 @@ public class ColumnExp
|
||||
implements SQLExpression
|
||||
{
|
||||
/** The table that hosts the column we reference, or null. */
|
||||
final public Class pClass;
|
||||
final public Class<? extends PersistentRecord> pClass;
|
||||
|
||||
/** The name of the column we reference. */
|
||||
final public String pColumn;
|
||||
@@ -43,7 +44,7 @@ public class ColumnExp
|
||||
this(null, column);
|
||||
}
|
||||
|
||||
public ColumnExp (Class c, String column)
|
||||
public ColumnExp (Class<? extends PersistentRecord> c, String column)
|
||||
{
|
||||
super();
|
||||
pClass = c;
|
||||
@@ -51,7 +52,7 @@ public class ColumnExp
|
||||
}
|
||||
|
||||
// from SQLExpression
|
||||
public void appendExpression (ConstructedQuery query, StringBuilder builder)
|
||||
public void appendExpression (ConstructedQuery<?> query, StringBuilder builder)
|
||||
{
|
||||
if (pClass == null || query == null) {
|
||||
builder.append(pColumn);
|
||||
|
||||
@@ -34,7 +34,7 @@ public interface SQLExpression
|
||||
* Construct the SQL form of this expression. The implementor is invited to call methods on the
|
||||
* Query object to e.g. resolve the current table abbreviations associated with classes.
|
||||
*/
|
||||
public void appendExpression (ConstructedQuery query, StringBuilder builder);
|
||||
public void appendExpression (ConstructedQuery<?> query, StringBuilder builder);
|
||||
|
||||
/**
|
||||
* Bind any objects that were referenced in the generated SQL. For each ? that appears in the
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.samskivert.jdbc.depot.ConstructedQuery;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.jdbc.depot.expression.ColumnExp;
|
||||
import com.samskivert.jdbc.depot.expression.SQLExpression;
|
||||
import com.samskivert.jdbc.depot.operator.SQLOperator.BinaryOperator;
|
||||
@@ -45,7 +46,7 @@ public abstract class Conditionals
|
||||
this(new ColumnExp(null, pColumn));
|
||||
}
|
||||
|
||||
public IsNull (Class pClass, String pColumn)
|
||||
public IsNull (Class<? extends PersistentRecord> pClass, String pColumn)
|
||||
{
|
||||
this(new ColumnExp(pClass, pColumn));
|
||||
}
|
||||
@@ -161,12 +162,13 @@ public abstract class Conditionals
|
||||
this(new ColumnExp(null, pColumn), values.toArray(new Comparable[values.size()]));
|
||||
}
|
||||
|
||||
public In (Class pClass, String pColumn, Comparable... values)
|
||||
public In (Class<? extends PersistentRecord> pClass, String pColumn, Comparable... values)
|
||||
{
|
||||
this(new ColumnExp(pClass, pColumn), values);
|
||||
}
|
||||
|
||||
public In (Class pClass, String pColumn, Collection<? extends Comparable> values)
|
||||
public In (Class<? extends PersistentRecord> pClass, String pColumn,
|
||||
Collection<? extends Comparable> values)
|
||||
{
|
||||
this(new ColumnExp(pClass, pColumn), values.toArray(new Comparable[values.size()]));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user