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()));
|
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
|
* 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
|
* clauses are used to evaluate a deletion. Attempts to use other clauses will result in
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
|
|
||||||
package com.samskivert.depot.impl;
|
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.PersistentRecord;
|
||||||
import com.samskivert.depot.expression.SQLExpression;
|
import com.samskivert.depot.expression.SQLExpression;
|
||||||
import com.samskivert.depot.util.*; // TupleN
|
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 (
|
public static <T extends PersistentRecord, V> Projector<T,V> create (
|
||||||
Class<T> ptype, SQLExpression<V> column)
|
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) {
|
public V createObject (Object[] results) {
|
||||||
@SuppressWarnings("unchecked") V result = (V)results[0];
|
@SuppressWarnings("unchecked") V result = (V)results[0];
|
||||||
return result;
|
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 (
|
public static <T extends PersistentRecord, V1, V2> Projector<T,Tuple2<V1,V2>> create (
|
||||||
Class<T> ptype, SQLExpression<V1> col1, SQLExpression<V2> col2)
|
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) {
|
public Tuple2<V1,V2> createObject (Object[] results) {
|
||||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
@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 (
|
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)
|
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) {
|
public Tuple3<V1,V2,V3> createObject (Object[] results) {
|
||||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
||||||
@@ -72,7 +77,7 @@ public abstract class Projector<T extends PersistentRecord,R>
|
|||||||
SQLExpression<V4> col4)
|
SQLExpression<V4> col4)
|
||||||
{
|
{
|
||||||
return new Projector<T, Tuple4<V1,V2,V3,V4>>(
|
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) {
|
public Tuple4<V1,V2,V3,V4> createObject (Object[] results) {
|
||||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
@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)
|
SQLExpression<V4> col4, SQLExpression<V5> col5)
|
||||||
{
|
{
|
||||||
return new Projector<T, Tuple5<V1,V2,V3,V4,V5>>(
|
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) {
|
public Tuple5<V1,V2,V3,V4,V5> createObject (Object[] results) {
|
||||||
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
@SuppressWarnings("unchecked") V1 r1 = (V1)results[0];
|
||||||
@SuppressWarnings("unchecked") V2 r2 = (V2)results[1];
|
@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 Class<T> ptype;
|
||||||
public final SQLExpression<?>[] selexps;
|
public final SQLExpression<?>[] selexps;
|
||||||
|
|
||||||
|
|||||||
@@ -195,6 +195,25 @@ public class ProjectionTest extends TestBase
|
|||||||
// MathFuncs.trunc(TestRecord.AWESOMENESS)).doubleValue(), 0.0001);
|
// 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
|
// 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
|
// clean up after ourselves in every test; thus we go ahead and share a repository
|
||||||
protected TestRepository _repo = createTestRepository();
|
protected TestRepository _repo = createTestRepository();
|
||||||
|
|||||||
Reference in New Issue
Block a user