@Computed support from Zell.

git-svn-id: https://samskivert.googlecode.com/svn/trunk@1951 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2006-10-13 21:39:49 +00:00
parent c991d80c88
commit cacfd18a8c
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
_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];
int jj = 0;
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
if (hasPrimaryKey()) {
String[] indices = new String[_pkColumns.size()];
@@ -306,7 +318,7 @@ public class DepotMarshaller<T>
columns.add(rs.getString("COLUMN_NAME"));
}
for (String fname : _allFields) {
for (String fname : _columnFields) {
FieldMarshaller fmarsh = _fields.get(fname);
if (columns.contains(fmarsh.getColumnName())) {
continue;
@@ -372,9 +384,9 @@ public class DepotMarshaller<T>
try {
StringBuilder insert = new StringBuilder();
insert.append("insert into ").append(getTableName());
insert.append(" (").append(StringUtil.join(_allFields, ","));
insert.append(" (").append(StringUtil.join(_columnFields, ","));
insert.append(")").append(" values(");
for (int ii = 0; ii < _allFields.length; ii++) {
for (int ii = 0; ii < _columnFields.length; ii++) {
if (ii > 0) {
insert.append(", ");
}
@@ -385,7 +397,7 @@ public class DepotMarshaller<T>
// TODO: handle primary key, nullable fields specially?
PreparedStatement pstmt = conn.prepareStatement(insert.toString());
int idx = 0;
for (String field : _allFields) {
for (String field : _columnFields) {
_fields.get(field).setValue(po, pstmt, ++idx);
}
return pstmt;
@@ -437,7 +449,7 @@ public class DepotMarshaller<T>
public PreparedStatement createUpdate (Connection conn, Object po, Key key)
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. */
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
* definition. */
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
StringBuilder builder = new StringBuilder();
if (column != null && !StringUtil.isBlank(column.columnDefinition())) {
@@ -91,7 +91,7 @@ public abstract class Query<T>
throw new RuntimeException("createQuery() called with _mainClass == null");
}
DepotMarshaller mainMarshaller = _classMap.get(_mainType);
DepotMarshaller<?> mainMarshaller = _classMap.get(_mainType);
String[] fields = mainMarshaller._allFields;
StringBuilder query = new StringBuilder("select ");
for (int ii = 0; ii < fields.length; ii ++) {
@@ -101,8 +101,11 @@ public abstract class Query<T>
FieldOverrideClause clause = _disMap.get(fields[ii]);
if (clause != null) {
clause.appendClause(this, query);
} else {
} else if (mainMarshaller._fields.get(fields[ii]).getColumnDefinition() != null) {
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 ");
@@ -63,6 +63,7 @@ public class FieldOverrideClause
public void appendClause (Query query, StringBuilder builder)
{
_override.appendExpression(query, builder);
builder.append(" as ").append(_field);
}
// from QueryClause