@Computed support from Zell.

This commit is contained in:
Michael Bayne
2006-10-13 21:39:49 +00:00
parent 02126dcce9
commit 93bbbf06a9
5 changed files with 65 additions and 9 deletions
@@ -0,0 +1,31 @@
//
// $Id$
//
// samskivert library - useful routines for java programs
// Copyright (C) 2006 Michael Bayne
//
// 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;
/**
* 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}.
*
* TODO: Add fieldDefinition="count (*)" or somesuch.
*/
public @interface Computed
{
}
@@ -172,11 +172,23 @@ public class DepotMarshaller<T>
// generate our full list of fields/columns for use in queries // generate our full list of fields/columns for use in queries
_allFields = fields.toArray(new String[fields.size()]); _allFields = fields.toArray(new String[fields.size()]);
// create the SQL used to create and migrate our table // figure out the list of fields that correspond to actual table columns and create the SQL
// used to create and migrate our table
_columnFields = new String[_allFields.length];
_columnDefinitions = new String[_allFields.length]; _columnDefinitions = new String[_allFields.length];
int jj = 0;
for (int ii = 0; ii < _allFields.length; ii++) { for (int ii = 0; ii < _allFields.length; ii++) {
_columnDefinitions[ii] = _fields.get(_allFields[ii]).getColumnDefinition(); // include all persistent non-computed fields
String colDef = _fields.get(_allFields[ii]).getColumnDefinition();
if (colDef != null) {
_columnFields[jj] = _allFields[ii];
_columnDefinitions[jj] = colDef;
jj ++;
}
} }
_columnFields = ArrayUtil.splice(_columnFields, jj);
_columnDefinitions = ArrayUtil.splice(_columnDefinitions, jj);
// add the primary key, if we have one // add the primary key, if we have one
if (hasPrimaryKey()) { if (hasPrimaryKey()) {
String[] indices = new String[_pkColumns.size()]; String[] indices = new String[_pkColumns.size()];
@@ -306,7 +318,7 @@ public class DepotMarshaller<T>
columns.add(rs.getString("COLUMN_NAME")); columns.add(rs.getString("COLUMN_NAME"));
} }
for (String fname : _allFields) { for (String fname : _columnFields) {
FieldMarshaller fmarsh = _fields.get(fname); FieldMarshaller fmarsh = _fields.get(fname);
if (columns.contains(fmarsh.getColumnName())) { if (columns.contains(fmarsh.getColumnName())) {
continue; continue;
@@ -372,9 +384,9 @@ public class DepotMarshaller<T>
try { try {
StringBuilder insert = new StringBuilder(); StringBuilder insert = new StringBuilder();
insert.append("insert into ").append(getTableName()); insert.append("insert into ").append(getTableName());
insert.append(" (").append(StringUtil.join(_allFields, ",")); insert.append(" (").append(StringUtil.join(_columnFields, ","));
insert.append(")").append(" values("); insert.append(")").append(" values(");
for (int ii = 0; ii < _allFields.length; ii++) { for (int ii = 0; ii < _columnFields.length; ii++) {
if (ii > 0) { if (ii > 0) {
insert.append(", "); insert.append(", ");
} }
@@ -385,7 +397,7 @@ public class DepotMarshaller<T>
// TODO: handle primary key, nullable fields specially? // TODO: handle primary key, nullable fields specially?
PreparedStatement pstmt = conn.prepareStatement(insert.toString()); PreparedStatement pstmt = conn.prepareStatement(insert.toString());
int idx = 0; int idx = 0;
for (String field : _allFields) { for (String field : _columnFields) {
_fields.get(field).setValue(po, pstmt, ++idx); _fields.get(field).setValue(po, pstmt, ++idx);
} }
return pstmt; return pstmt;
@@ -437,7 +449,7 @@ public class DepotMarshaller<T>
public PreparedStatement createUpdate (Connection conn, Object po, Key key) public PreparedStatement createUpdate (Connection conn, Object po, Key key)
throws SQLException throws SQLException
{ {
return createUpdate(conn, po, key, _allFields); return createUpdate(conn, po, key, _columnFields);
} }
/** /**
@@ -599,6 +611,9 @@ public class DepotMarshaller<T>
/** The persisent fields of our object, in definition order. */ /** The persisent fields of our object, in definition order. */
protected String[] _allFields; protected String[] _allFields;
/** The fields of our object with directly corresponding table columns. */
protected String[] _columnFields;
/** The version of our persistent object schema as specified in the class /** The version of our persistent object schema as specified in the class
* definition. */ * definition. */
protected int _schemaVersion = -1; protected int _schemaVersion = -1;
@@ -172,6 +172,12 @@ public abstract class FieldMarshaller
} }
} }
// if this field is @Computed, it has no SQL definition
if (field.getAnnotation(Computed.class) != null) {
_columnDefinition = null;
return;
}
// create our SQL column definition // create our SQL column definition
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
if (column != null && !StringUtil.isBlank(column.columnDefinition())) { if (column != null && !StringUtil.isBlank(column.columnDefinition())) {
@@ -91,7 +91,7 @@ public abstract class Query<T>
throw new RuntimeException("createQuery() called with _mainClass == null"); throw new RuntimeException("createQuery() called with _mainClass == null");
} }
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 ");
for (int ii = 0; ii < fields.length; ii ++) { for (int ii = 0; ii < fields.length; ii ++) {
@@ -101,8 +101,11 @@ public abstract class Query<T>
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 { } else if (mainMarshaller._fields.get(fields[ii]).getColumnDefinition() != null) {
query.append("T.").append(fields[ii]); query.append("T.").append(fields[ii]);
} else {
throw new SQLException(
"Computed field must be overridden [field=" + fields[ii] + "]");
} }
} }
query.append(" from " + mainMarshaller.getTableName() + " as T "); query.append(" from " + mainMarshaller.getTableName() + " as T ");
@@ -63,6 +63,7 @@ public class FieldOverrideClause
public void appendClause (Query query, StringBuilder builder) public void appendClause (Query query, StringBuilder builder)
{ {
_override.appendExpression(query, builder); _override.appendExpression(query, builder);
builder.append(" as ").append(_field);
} }
// from QueryClause // from QueryClause