Index: org/castor/jdo/engine/SQLTypeInfos.java =================================================================== RCS file: /scm/castor/castor/src/main/org/castor/jdo/engine/SQLTypeInfos.java,v retrieving revision 1.1 diff -u -r1.1 SQLTypeInfos.java --- org/castor/jdo/engine/SQLTypeInfos.java 25 Nov 2005 23:37:03 -0000 1.1 +++ org/castor/jdo/engine/SQLTypeInfos.java 17 Dec 2005 20:14:38 -0000 @@ -19,9 +19,12 @@ import java.io.InputStream; import java.sql.Blob; import java.sql.Clob; +import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.GregorianCalendar; @@ -281,6 +284,15 @@ // by Castor to java.io.InputStream and java.io.Reader, respectively, // while JDBC driver expects java.sql.Blob and java.sql.Clob. switch (sqlType) { + case Types.TIME: + stmt.setTime(index, (Time) value, getCalendar()); + break; + case Types.DATE: + stmt.setDate(index, (Date) value, getCalendar()); + break; + case Types.TIMESTAMP: + stmt.setTimestamp(index, (Timestamp) value, getCalendar()); + break; case Types.FLOAT: case Types.DOUBLE: stmt.setDouble(index, ((Double) value).doubleValue()); Index: org/exolab/castor/jdo/engine/SQLEngine.java =================================================================== RCS file: /scm/castor/castor/src/main/org/exolab/castor/jdo/engine/SQLEngine.java,v retrieving revision 1.42 diff -u -r1.42 SQLEngine.java --- org/exolab/castor/jdo/engine/SQLEngine.java 1 Dec 2005 20:18:53 -0000 1.42 +++ org/exolab/castor/jdo/engine/SQLEngine.java 17 Dec 2005 20:14:38 -0000 @@ -51,7 +51,9 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -59,6 +61,7 @@ import java.util.Map; import java.util.Properties; import java.util.Stack; +import java.util.TimeZone; import java.util.Vector; import org.apache.commons.logging.Log; @@ -90,6 +93,7 @@ import org.exolab.castor.persist.spi.PersistenceFactory; import org.exolab.castor.persist.spi.PersistenceQuery; import org.exolab.castor.persist.spi.QueryExpression; +import org.exolab.castor.util.LocalConfiguration; import org.exolab.castor.util.Messages; import org.exolab.castor.util.SqlBindParser; @@ -179,6 +183,31 @@ * Collection of all the ClassDescriptor that extend this one (closure) */ private Collection _extendingClassDescriptors; + + /** Thread local Calendar instance pool. */ + private static final ThreadLocal THREAD_SAFE_CALENDAR = new ThreadLocal() { + // The Calendar passed to ResultSet.getTimestamp() etc can actually + // be modified depending on the database driver implementation. To guard + // against synchronization issues, we need to pass either a local + // instance (which is expensive, creating one for each call), or create + // a thread-local instance (which only gets created once per thread). + // The latter is what this is for. + public Object initialValue() { return new GregorianCalendar(); } + }; + + /** Time zone based on setting in castor.properties file (or + * default time zone if not specified). */ + private static final TimeZone TIME_ZONE; + + static { + String name = "org.exolab.castor.jdo.defaultTimeZone"; + String zone = LocalConfiguration.getInstance().getProperty(name, ""); + if (zone.length() == 0) { + TIME_ZONE = TimeZone.getDefault(); + } else { + TIME_ZONE = TimeZone.getTimeZone(zone); + } + } SQLEngine( JDOClassDescriptor clsDesc, PersistenceFactory factory, String stampField ) throws MappingException { @@ -515,6 +544,10 @@ ColumnInfo col = _fields[field].columns[column]; if (object == null || col.convertFrom == null) return object; + Class fieldType = ((JDOFieldDescriptor) _fields[field].fieldDescriptor).getFieldType(); + if (fieldType.getName().equals("java.util.Date")) { + // TODO do somethin special, and remove code from SQLTypeInfos.setValue() again + } return col.convertFrom.convert(object, col.convertParam); } @@ -1982,7 +2015,7 @@ final String name; /** - * SQL type of teh coplumn + * SQL type of the column */ final int sqlType; @@ -2001,8 +2034,16 @@ */ final String convertParam; - ColumnInfo( String name, int type, TypeConvertor convertTo, - TypeConvertor convertFrom, String convertParam ) { + /** + * Creates an instance of ColumnInfo + * @param name Name of the column + * @param type SQL type fo the column + * @param convertTo Type convertor used for converting to SQL type + * @param convertFrom Type convertor used for converting from SQL type + * @param convertParam Type conversion parameter + */ + ColumnInfo(String name, int type, TypeConvertor convertTo, + TypeConvertor convertFrom, String convertParam) { this.name = name; this.sqlType = type; this.convertTo = convertTo; @@ -2010,35 +2051,40 @@ this.convertParam = convertParam; } - /* (non-Javadoc) + /** + * @inheritDoc * @see org.exolab.castor.persist.spi.Persistence.ColumnInfo#getName() */ public String getName() { return name; } - /* (non-Javadoc) + /** + * @inheritDoc * @see org.exolab.castor.persist.spi.Persistence.ColumnInfo#getSqlType() */ public int getSqlType() { return sqlType; } - /* (non-Javadoc) + /** + * @inheritDoc * @see org.exolab.castor.persist.spi.Persistence.ColumnInfo#getConvertTo() */ public TypeConvertor getConvertTo() { return convertTo; } - /* (non-Javadoc) + /** + * @inheritDoc * @see org.exolab.castor.persist.spi.Persistence.ColumnInfo#getConvertFrom() */ public TypeConvertor getConvertFrom() { return convertFrom; } - /* (non-Javadoc) + /** + * @inheritDoc * @see org.exolab.castor.persist.spi.Persistence.ColumnInfo#getConvertParam() */ public String getConvertParam() { @@ -2631,4 +2677,18 @@ return null; } } + + /** + * Get a Calendar instance for current thread. + * + * @return A Calendar instance for current thread. + */ + private static Calendar getCalendar() { + // We have to reset the time zone each time in case the result set + // implementation changes it. + Calendar calendar = (Calendar) THREAD_SAFE_CALENDAR.get(); + calendar.setTimeZone(TIME_ZONE); + return calendar; + } + }