Added a mechanism for selecting results into a simple result class that relies
only on a matching public constructor. This version is not type-safe, but I'll also be adding an additional mechanism to do selections like this that uses a type-safe builder approach, which comes at the cost of a healthy dose of boilerplate code.
This commit is contained in:
@@ -465,6 +465,15 @@ public class Query<T extends PersistentRecord>
|
||||
getClauses()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns just the supplied expression from the rows matching the query.
|
||||
*/
|
||||
public <V> List<V> selectInto (Class<V> resultClass, SQLExpression<?>... selexps)
|
||||
{
|
||||
Projector<T,V> proj = Projector.create(_pclass, resultClass, selexps);
|
||||
return _ctx.invoke(new FindAllQuery.Projection<T,V>(_ctx, proj, getClauses()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the records that match the configured query clauses. Note that only the where
|
||||
* clauses are used to evaluate a deletion. Attempts to use other clauses will result in
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
package com.samskivert.depot.impl;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import com.samskivert.depot.DatabaseException;
|
||||
import com.samskivert.depot.PersistentRecord;
|
||||
import com.samskivert.depot.expression.SQLExpression;
|
||||
import com.samskivert.depot.util.*; // TupleN
|
||||
@@ -33,7 +37,7 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
public static <T extends PersistentRecord, V> Projector<T,V> create (
|
||||
Class<T> ptype, SQLExpression<V> column)
|
||||
{
|
||||
return new Projector<T, V>(ptype, new SQLExpression[] { column }) {
|
||||
return new Projector<T, V>(ptype, new SQLExpression<?>[] { column }) {
|
||||
public V createObject (Object[] results) {
|
||||
@SuppressWarnings("unchecked") V result = (V)results[0];
|
||||
return result;
|
||||
@@ -44,7 +48,7 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
public static <T extends PersistentRecord, V1, V2> Projector<T,Tuple2<V1,V2>> create (
|
||||
Class<T> ptype, SQLExpression<V1> col1, SQLExpression<V2> col2)
|
||||
{
|
||||
return new Projector<T, Tuple2<V1,V2>>(ptype, new SQLExpression[] { col1, col2 }) {
|
||||
return new Projector<T, Tuple2<V1,V2>>(ptype, new SQLExpression<?>[] { col1, col2 }) {
|
||||
public Tuple2<V1,V2> createObject (Object[] results) {
|
||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
||||
@@ -56,7 +60,8 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
public static <T extends PersistentRecord, V1, V2, V3> Projector<T,Tuple3<V1,V2,V3>> create (
|
||||
Class<T> ptype, SQLExpression<V1> col1, SQLExpression<V2> col2, SQLExpression<V3> col3)
|
||||
{
|
||||
return new Projector<T, Tuple3<V1,V2,V3>>(ptype, new SQLExpression[] { col1, col2, col3 }) {
|
||||
return new Projector<T, Tuple3<V1,V2,V3>>(
|
||||
ptype, new SQLExpression<?>[] { col1, col2, col3 }) {
|
||||
public Tuple3<V1,V2,V3> createObject (Object[] results) {
|
||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
||||
@@ -72,7 +77,7 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
SQLExpression<V4> col4)
|
||||
{
|
||||
return new Projector<T, Tuple4<V1,V2,V3,V4>>(
|
||||
ptype, new SQLExpression[] { col1, col2, col3, col4 }) {
|
||||
ptype, new SQLExpression<?>[] { col1, col2, col3, col4 }) {
|
||||
public Tuple4<V1,V2,V3,V4> createObject (Object[] results) {
|
||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
||||
@@ -89,7 +94,7 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
SQLExpression<V4> col4, SQLExpression<V5> col5)
|
||||
{
|
||||
return new Projector<T, Tuple5<V1,V2,V3,V4,V5>>(
|
||||
ptype, new SQLExpression[] { col1, col2, col3, col4, col5 }) {
|
||||
ptype, new SQLExpression<?>[] { col1, col2, col3, col4, col5 }) {
|
||||
public Tuple5<V1,V2,V3,V4,V5> createObject (Object[] results) {
|
||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
||||
@@ -101,6 +106,31 @@ public abstract class Projector<T extends PersistentRecord,R>
|
||||
};
|
||||
}
|
||||
|
||||
public static <T extends PersistentRecord, V> Projector<T,V> create (
|
||||
Class<T> ptype, final Class<V> resultType, SQLExpression<?>... selexps)
|
||||
{
|
||||
return new Projector<T, V>(ptype, selexps) {
|
||||
public V createObject (Object[] results) {
|
||||
try {
|
||||
return _ctor.newInstance(results);
|
||||
} catch (InstantiationException e) {
|
||||
throw new DatabaseException("Invalid constructor supplied for projection", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new DatabaseException("Invalid constructor supplied for projection", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getCause();
|
||||
if (t instanceof RuntimeException) {
|
||||
throw (RuntimeException)t;
|
||||
} else {
|
||||
throw new DatabaseException("Error constructing result object", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Constructor<V> _ctor = (Constructor<V>)resultType.getConstructors()[0];
|
||||
};
|
||||
}
|
||||
|
||||
public final Class<T> ptype;
|
||||
public final SQLExpression<?>[] selexps;
|
||||
|
||||
|
||||
@@ -195,6 +195,25 @@ public class ProjectionTest extends TestBase
|
||||
// MathFuncs.trunc(TestRecord.AWESOMENESS)).doubleValue(), 0.0001);
|
||||
}
|
||||
|
||||
@Test public void testSelectInfo ()
|
||||
{
|
||||
assertEquals("[0 Elvis, 1 Elvis]",
|
||||
_repo.from(TestRecord.class).where(TestRecord.RECORD_ID.lessThan(2)).
|
||||
selectInto(IdName.class, TestRecord.RECORD_ID, TestRecord.NAME).toString());
|
||||
}
|
||||
|
||||
protected static class IdName {
|
||||
public final int id;
|
||||
public final String name;
|
||||
public IdName (int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
public String toString() {
|
||||
return id + " " + name;
|
||||
}
|
||||
}
|
||||
|
||||
// the HSQL in-memory database persists for the lifetime of the VM, which means we have to
|
||||
// clean up after ourselves in every test; thus we go ahead and share a repository
|
||||
protected TestRepository _repo = createTestRepository();
|
||||
|
||||
Reference in New Issue
Block a user