@Computed enhancements from Zell.
This commit is contained in:
@@ -20,12 +20,22 @@
|
|||||||
|
|
||||||
package com.samskivert.jdbc.depot;
|
package com.samskivert.jdbc.depot;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a field as computed, meaning it's ignored for schema purposes, it does not directly
|
* Marks a field as computed, meaning it's ignored for schema purposes, it does not directly
|
||||||
* correspond to a column in a table, and thus its value must be overridden in the {@link Query}.
|
* correspond to a column in a table, and thus its value must be overridden in the {@link Query}.
|
||||||
*
|
|
||||||
* TODO: Add fieldDefinition="count (*)" or somesuch.
|
|
||||||
*/
|
*/
|
||||||
|
@Retention(value=RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
public @interface Computed
|
public @interface Computed
|
||||||
{
|
{
|
||||||
|
/** If this value is false, the field is not populated by Depot at all. */
|
||||||
|
boolean required() default true;
|
||||||
|
|
||||||
|
/** A non-empty value here is taken as literal SQL and used to populate the computed field. */
|
||||||
|
String fieldDefinition() default "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,14 @@ public abstract class FieldMarshaller
|
|||||||
return _field;
|
return _field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Computed annotation on this field, if any.
|
||||||
|
*/
|
||||||
|
public Computed getComputed ()
|
||||||
|
{
|
||||||
|
return _computed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the GeneratedValue annotation on this field, if any.
|
* Returns the GeneratedValue annotation on this field, if any.
|
||||||
*/
|
*/
|
||||||
@@ -172,8 +180,9 @@ public abstract class FieldMarshaller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_computed = field.getAnnotation(Computed.class);
|
||||||
// if this field is @Computed, it has no SQL definition
|
// if this field is @Computed, it has no SQL definition
|
||||||
if (field.getAnnotation(Computed.class) != null) {
|
if (_computed != null) {
|
||||||
_columnDefinition = null;
|
_columnDefinition = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -383,5 +392,6 @@ public abstract class FieldMarshaller
|
|||||||
|
|
||||||
protected Field _field;
|
protected Field _field;
|
||||||
protected String _columnName, _columnDefinition;
|
protected String _columnName, _columnDefinition;
|
||||||
|
protected Computed _computed;
|
||||||
protected GeneratedValue _generatedValue;
|
protected GeneratedValue _generatedValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,18 +94,37 @@ public abstract class Query<T>
|
|||||||
DepotMarshaller<?> mainMarshaller = _classMap.get(_mainType);
|
DepotMarshaller<?> mainMarshaller = _classMap.get(_mainType);
|
||||||
String[] fields = mainMarshaller._allFields;
|
String[] fields = mainMarshaller._allFields;
|
||||||
StringBuilder query = new StringBuilder("select ");
|
StringBuilder query = new StringBuilder("select ");
|
||||||
|
boolean skip = true;
|
||||||
for (int ii = 0; ii < fields.length; ii ++) {
|
for (int ii = 0; ii < fields.length; ii ++) {
|
||||||
if (ii > 0) {
|
if (!skip) {
|
||||||
query.append(", ");
|
query.append(", ");
|
||||||
}
|
}
|
||||||
|
skip = false;
|
||||||
|
|
||||||
FieldOverrideClause clause = _disMap.get(fields[ii]);
|
FieldOverrideClause clause = _disMap.get(fields[ii]);
|
||||||
if (clause != null) {
|
if (clause != null) {
|
||||||
clause.appendClause(this, query);
|
clause.appendClause(this, query);
|
||||||
} else if (mainMarshaller._fields.get(fields[ii]).getColumnDefinition() != null) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Computed computed = mainMarshaller._fields.get(fields[ii]).getComputed();
|
||||||
|
if (computed == null) {
|
||||||
|
// if it's neither overridden nor computed, it's a standard field
|
||||||
query.append("T.").append(fields[ii]);
|
query.append("T.").append(fields[ii]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the computed field has a literal SQL definition
|
||||||
|
if (computed.fieldDefinition().length() > 0) {
|
||||||
|
query.append(computed.fieldDefinition() + " as " + fields[ii]);
|
||||||
|
|
||||||
|
} else if (!computed.required()) {
|
||||||
|
// or if we can simply ignore the field
|
||||||
|
skip = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new SQLException(
|
throw new SQLException(
|
||||||
"Computed field must be overridden [field=" + fields[ii] + "]");
|
"@Computed(required) field without definition [field=" + fields[ii] + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query.append(" from " + mainMarshaller.getTableName() + " as T ");
|
query.append(" from " + mainMarshaller.getTableName() + " as T ");
|
||||||
|
|||||||
Reference in New Issue
Block a user