Extracted findAllKeys() query into a helper class, made it possible for Query
to request a read-write connection.
This commit is contained in:
@@ -309,68 +309,10 @@ public abstract class DepotRepository
|
|||||||
* the latest data.
|
* the latest data.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> List<Key<T>> findAllKeys (
|
protected <T extends PersistentRecord> List<Key<T>> findAllKeys (
|
||||||
final Class<T> type, boolean forUpdate, Collection<? extends QueryClause> clauses)
|
Class<T> type, boolean forUpdate, Collection<? extends QueryClause> clauses)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
final List<Key<T>> keys = Lists.newArrayList();
|
return _ctx.invoke(new FindAllKeysQuery<T>(_ctx, type, forUpdate, clauses));
|
||||||
final DepotMarshaller<T> marsh = _ctx.getMarshaller(type);
|
|
||||||
SelectClause<T> select = new SelectClause<T>(type, marsh.getPrimaryKeyFields(), clauses);
|
|
||||||
final SQLBuilder builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(_ctx, select));
|
|
||||||
builder.newQuery(select);
|
|
||||||
|
|
||||||
if (forUpdate) {
|
|
||||||
_ctx.invoke(new Modifier(null) {
|
|
||||||
@Override
|
|
||||||
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
|
||||||
PreparedStatement stmt = builder.prepare(conn);
|
|
||||||
try {
|
|
||||||
ResultSet rs = stmt.executeQuery();
|
|
||||||
while (rs.next()) {
|
|
||||||
keys.add(marsh.makePrimaryKey(rs));
|
|
||||||
}
|
|
||||||
// TODO: cache this result?
|
|
||||||
if (PersistenceContext.CACHE_DEBUG) {
|
|
||||||
log.info("Loaded " + StringUtil.shortClassName(type) + " keys",
|
|
||||||
"count", keys.size());
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} finally {
|
|
||||||
JDBCUtil.close(stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override public void updateStats (Stats stats) {
|
|
||||||
stats.noteQuery(0, 1, 0, 0); // one uncached query
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_ctx.invoke(new Query.Trivial<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void invoke (PersistenceContext ctx, Connection conn,
|
|
||||||
DatabaseLiaison liaison) throws SQLException {
|
|
||||||
PreparedStatement stmt = builder.prepare(conn);
|
|
||||||
try {
|
|
||||||
ResultSet rs = stmt.executeQuery();
|
|
||||||
while (rs.next()) {
|
|
||||||
keys.add(marsh.makePrimaryKey(rs));
|
|
||||||
}
|
|
||||||
// TODO: cache this result?
|
|
||||||
if (PersistenceContext.CACHE_DEBUG) {
|
|
||||||
log.info("Loaded " + StringUtil.shortClassName(type) + " keys",
|
|
||||||
"count", keys.size());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
JDBCUtil.close(stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void updateStats (Stats stats) {
|
|
||||||
stats.noteQuery(0, 1, 0, 0); // one uncached query
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Depot library - a Java relational persistence library
|
||||||
|
// Copyright (C) 2006-2008 Michael Bayne and 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.depot;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import com.samskivert.jdbc.DatabaseLiaison;
|
||||||
|
import com.samskivert.jdbc.JDBCUtil;
|
||||||
|
|
||||||
|
import com.samskivert.depot.clause.QueryClause;
|
||||||
|
import com.samskivert.depot.clause.SelectClause;
|
||||||
|
|
||||||
|
import static com.samskivert.depot.Log.log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all primary keys for the records matching the supplied clause.
|
||||||
|
*/
|
||||||
|
public class FindAllKeysQuery<T extends PersistentRecord> extends Query<List<Key<T>>>
|
||||||
|
{
|
||||||
|
public FindAllKeysQuery (PersistenceContext ctx, Class<T> type, boolean forUpdate,
|
||||||
|
Collection<? extends QueryClause> clauses)
|
||||||
|
throws DatabaseException
|
||||||
|
{
|
||||||
|
_forUpdate = forUpdate;
|
||||||
|
_marsh = ctx.getMarshaller(type);
|
||||||
|
_select = new SelectClause<T>(type, _marsh.getPrimaryKeyFields(), clauses);
|
||||||
|
_builder = ctx.getSQLBuilder(DepotTypes.getDepotTypes(ctx, _select));
|
||||||
|
_builder.newQuery(_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // from Query
|
||||||
|
public boolean isReadOnly ()
|
||||||
|
{
|
||||||
|
return !_forUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // from Query
|
||||||
|
public List<Key<T>> getCachedResult (PersistenceContext ctx)
|
||||||
|
{
|
||||||
|
return null; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // from Query
|
||||||
|
public List<Key<T>> invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
List<Key<T>> keys = Lists.newArrayList();
|
||||||
|
PreparedStatement stmt = _builder.prepare(conn);
|
||||||
|
try {
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
keys.add(_marsh.makePrimaryKey(rs));
|
||||||
|
}
|
||||||
|
// TODO: cache this result?
|
||||||
|
if (PersistenceContext.CACHE_DEBUG) {
|
||||||
|
log.info("Loaded " + _marsh.getTableName(), "count", keys.size());
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
} finally {
|
||||||
|
JDBCUtil.close(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // from Query
|
||||||
|
public void updateStats (Stats stats)
|
||||||
|
{
|
||||||
|
stats.noteQuery(0, 1, 0, 0); // one uncached query
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean _forUpdate;
|
||||||
|
protected SQLBuilder _builder;
|
||||||
|
protected DepotMarshaller<T> _marsh;
|
||||||
|
protected SelectClause<T> _select;
|
||||||
|
}
|
||||||
@@ -49,8 +49,7 @@ import static com.samskivert.depot.Log.log;
|
|||||||
* This class implements the functionality required by {@link DepotRepository#findAll}: fetch
|
* This class implements the functionality required by {@link DepotRepository#findAll}: fetch
|
||||||
* a collection of persistent objects using one of two included strategies.
|
* a collection of persistent objects using one of two included strategies.
|
||||||
*/
|
*/
|
||||||
public abstract class FindAllQuery<T extends PersistentRecord>
|
public abstract class FindAllQuery<T extends PersistentRecord> extends Query<List<T>>
|
||||||
implements Query<List<T>>
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The two-pass collection query implementation. See {@link DepotRepository#findAll} for
|
* The two-pass collection query implementation. See {@link DepotRepository#findAll} for
|
||||||
@@ -76,7 +75,7 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_select = new SelectClause<T>(_type, _marsh.getPrimaryKeyFields(), clauses);
|
_select = new SelectClause<T>(_type, _marsh.getPrimaryKeyFields(), clauses);
|
||||||
_builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(ctx, _select));
|
_builder = ctx.getSQLBuilder(DepotTypes.getDepotTypes(ctx, _select));
|
||||||
_builder.newQuery(_select);
|
_builder.newQuery(_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +94,7 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
Key<T> key = _marsh.makePrimaryKey(rs);
|
Key<T> key = _marsh.makePrimaryKey(rs);
|
||||||
allKeys.add(key);
|
allKeys.add(key);
|
||||||
|
|
||||||
T value = _ctx.<T>cacheLookup(key);
|
T value = ctx.<T>cacheLookup(key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@SuppressWarnings("unchecked") T newValue = (T) value.clone();
|
@SuppressWarnings("unchecked") T newValue = (T) value.clone();
|
||||||
entities.put(key, newValue);
|
entities.put(key, newValue);
|
||||||
@@ -124,7 +123,6 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
stats.noteQuery(0, 1, _cachedRecords, _uncachedRecords); // one uncached query
|
stats.noteQuery(0, 1, _cachedRecords, _uncachedRecords); // one uncached query
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SelectClause<T> _select;
|
|
||||||
protected int _cachedRecords, _uncachedRecords;
|
protected int _cachedRecords, _uncachedRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +146,7 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
Map<Key<T>, T> entities = Maps.newHashMap();
|
Map<Key<T>, T> entities = Maps.newHashMap();
|
||||||
Set<Key<T>> fetchKeys = Sets.newHashSet();
|
Set<Key<T>> fetchKeys = Sets.newHashSet();
|
||||||
for (Key<T> key : _keys) {
|
for (Key<T> key : _keys) {
|
||||||
T value = _ctx.<T>cacheLookup(key);
|
T value = ctx.<T>cacheLookup(key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@SuppressWarnings("unchecked") T newValue = (T) value.clone();
|
@SuppressWarnings("unchecked") T newValue = (T) value.clone();
|
||||||
entities.put(key, newValue);
|
entities.put(key, newValue);
|
||||||
@@ -213,49 +211,28 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
stats.noteQuery(0, 1, 0, _uncachedRecords);
|
stats.noteQuery(0, 1, 0, _uncachedRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SelectClause<T> _select;
|
|
||||||
protected int _uncachedRecords;
|
protected int _uncachedRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FindAllQuery (PersistenceContext ctx, Class<T> type)
|
@Override // from Query
|
||||||
throws DatabaseException
|
|
||||||
{
|
|
||||||
_ctx = ctx;
|
|
||||||
_type = type;
|
|
||||||
_marsh = _ctx.getMarshaller(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// from interface Query
|
|
||||||
public List<T> getCachedResult (PersistenceContext ctx)
|
public List<T> getCachedResult (PersistenceContext ctx)
|
||||||
{
|
{
|
||||||
return null; // TODO
|
return null; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// // from interface Query
|
@Override // from Operation
|
||||||
// public List<T> transformCacheHit (CacheKey key, List<T> bits)
|
|
||||||
// {
|
|
||||||
// if (bits == null) {
|
|
||||||
// return bits;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// List<T> result = Lists.newArrayList();
|
|
||||||
// for (T bit : bits) {
|
|
||||||
// if (bit != null) {
|
|
||||||
// @SuppressWarnings("unchecked") T cbit = (T) bit.clone();
|
|
||||||
// result.add(cbit);
|
|
||||||
// } else {
|
|
||||||
// result.add(null);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// from interface Operation
|
|
||||||
public void updateStats (Stats stats)
|
public void updateStats (Stats stats)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected FindAllQuery (PersistenceContext ctx, Class<T> type)
|
||||||
|
throws DatabaseException
|
||||||
|
{
|
||||||
|
_type = type;
|
||||||
|
_marsh = ctx.getMarshaller(type);
|
||||||
|
}
|
||||||
|
|
||||||
protected List<T> loadAndResolve (PersistenceContext ctx, Connection conn,
|
protected List<T> loadAndResolve (PersistenceContext ctx, Connection conn,
|
||||||
Collection<Key<T>> allKeys, Set<Key<T>> fetchKeys,
|
Collection<Key<T>> allKeys, Set<Key<T>> fetchKeys,
|
||||||
Map<Key<T>, T> entities, String origStmt)
|
Map<Key<T>, T> entities, String origStmt)
|
||||||
@@ -346,8 +323,8 @@ public abstract class FindAllQuery<T extends PersistentRecord>
|
|||||||
return builder.append(")").toString();
|
return builder.append(")").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PersistenceContext _ctx;
|
|
||||||
protected SQLBuilder _builder;
|
protected SQLBuilder _builder;
|
||||||
protected DepotMarshaller<T> _marsh;
|
protected DepotMarshaller<T> _marsh;
|
||||||
protected Class<T> _type;
|
protected Class<T> _type;
|
||||||
|
protected SelectClause<T> _select;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ import static com.samskivert.depot.Log.log;
|
|||||||
/**
|
/**
|
||||||
* The implementation of {@link DepotRepository#load} functionality.
|
* The implementation of {@link DepotRepository#load} functionality.
|
||||||
*/
|
*/
|
||||||
public class FindOneQuery<T extends PersistentRecord>
|
public class FindOneQuery<T extends PersistentRecord> extends Query<T>
|
||||||
implements Query<T>
|
|
||||||
{
|
{
|
||||||
public FindOneQuery (PersistenceContext ctx, Class<T> type, QueryClause[] clauses)
|
public FindOneQuery (PersistenceContext ctx, Class<T> type, QueryClause[] clauses)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
@@ -53,7 +52,7 @@ public class FindOneQuery<T extends PersistentRecord>
|
|||||||
_builder.newQuery(_select);
|
_builder.newQuery(_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
// from interface Query
|
@Override // from Query
|
||||||
public T getCachedResult (PersistenceContext ctx)
|
public T getCachedResult (PersistenceContext ctx)
|
||||||
{
|
{
|
||||||
CacheKey key = getCacheKey();
|
CacheKey key = getCacheKey();
|
||||||
@@ -70,7 +69,7 @@ public class FindOneQuery<T extends PersistentRecord>
|
|||||||
return cvalue;
|
return cvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from interface Query
|
@Override // from Query
|
||||||
public T invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
public T invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
@@ -110,7 +109,7 @@ public class FindOneQuery<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from interface Operation
|
@Override // from Operation
|
||||||
public void updateStats (Stats stats)
|
public void updateStats (Stats stats)
|
||||||
{
|
{
|
||||||
stats.noteQuery(0, 0, _cachedRecords, 1-_cachedRecords);
|
stats.noteQuery(0, 0, _cachedRecords, 1-_cachedRecords);
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ public abstract class Modifier implements Operation<Integer>
|
|||||||
_invalidator = invalidator;
|
_invalidator = invalidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from interface Operation
|
||||||
|
public boolean isReadOnly ()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// from interface Operation
|
// from interface Operation
|
||||||
public Integer invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ import com.samskivert.jdbc.DatabaseLiaison;
|
|||||||
*/
|
*/
|
||||||
public interface Operation<T>
|
public interface Operation<T>
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this operation is safe to invoke on a database mirror.
|
||||||
|
*/
|
||||||
|
public boolean isReadOnly ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the actual JDBC interactions associated with this operation.
|
* Performs the actual JDBC interactions associated with this operation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ public class PersistenceContext
|
|||||||
{
|
{
|
||||||
checkAreInitialized(); // le check du sanity
|
checkAreInitialized(); // le check du sanity
|
||||||
|
|
||||||
boolean isReadOnly = !(op instanceof Modifier);
|
boolean isReadOnly = op.isReadOnly();
|
||||||
Connection conn;
|
Connection conn;
|
||||||
long preConnect = System.nanoTime();
|
long preConnect = System.nanoTime();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -29,21 +29,16 @@ import com.samskivert.depot.PersistenceContext.CacheListener;
|
|||||||
/**
|
/**
|
||||||
* The base of all read-only queries.
|
* The base of all read-only queries.
|
||||||
*/
|
*/
|
||||||
public interface Query<T> extends Operation<T>
|
public abstract class Query<T>
|
||||||
|
implements Operation<T>
|
||||||
{
|
{
|
||||||
/** A simple base class for non-complex queries. */
|
/** A simple base class for non-complex queries. */
|
||||||
public abstract class Trivial<T> implements Query<T>
|
public static abstract class Trivial<T> extends Query<T>
|
||||||
{
|
{
|
||||||
public abstract T invoke (PersistenceContext ctx, Connection conn, DatabaseLiaison liaison)
|
@Override // from Query
|
||||||
throws SQLException;
|
|
||||||
|
|
||||||
public T getCachedResult (PersistenceContext ctx) {
|
public T getCachedResult (PersistenceContext ctx) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T transformCacheHit (CacheKey key, T value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,5 +46,11 @@ public interface Query<T> extends Operation<T>
|
|||||||
* method. If null is returned, the query will be {@link #invoke}d to obtain its result from
|
* method. If null is returned, the query will be {@link #invoke}d to obtain its result from
|
||||||
* persistent storage.
|
* persistent storage.
|
||||||
*/
|
*/
|
||||||
public T getCachedResult (PersistenceContext ctx);
|
public abstract T getCachedResult (PersistenceContext ctx);
|
||||||
|
|
||||||
|
// from interface Operation
|
||||||
|
public boolean isReadOnly ()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user