You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2008/08/08 01:21:58 UTC
svn commit: r683745 [15/22] - in /ibatis/trunk/java/ibatis-3: ./
ibatis-3-compat/ ibatis-3-compat/src/ ibatis-3-compat/src/main/
ibatis-3-compat/src/main/java/ ibatis-3-compat/src/main/java/com/
ibatis-3-compat/src/main/java/com/ibatis/ ibatis-3-compat...
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,213 @@
+package org.apache.ibatis.adhoc;
+
+import org.apache.ibatis.type.*;
+
+import java.sql.*;
+import java.util.*;
+
+public class AdHocExecutor {
+
+ public static final int NO_GENERATED_KEY = Integer.MIN_VALUE + 1001;
+
+ private Connection connection;
+ private TypeHandlerRegistry typeHandlerRegistry;
+ private boolean forceGeneratedKeySupport = false;
+
+ public AdHocExecutor(Connection connection, boolean forceGeneratedKeySupport) {
+ this.connection = connection;
+ this.typeHandlerRegistry = new TypeHandlerRegistry();
+ this.forceGeneratedKeySupport = forceGeneratedKeySupport;
+ }
+
+ public AdHocExecutor(Connection connection) {
+ this(connection, false);
+ }
+
+ /**
+ * Executes a SELECT statement that returns one row.
+ *
+ * @param sql The SQL
+ * @param args The arguments to be set on the statement.
+ * @return The number of rows impacted or BATCHED_RESULTS if the statements are being batched.
+ * @throws SQLException If more than one row is returned
+ */
+ public Map<String, Object> selectOne(String sql, Object... args) throws SQLException {
+ List<Map<String, Object>> results = selectAll(sql, args);
+ if (results.size() != 1) {
+ throw new SQLException("Statement returned " + results.size() + " results where exactly one (1) was expected.");
+ }
+ return results.get(0);
+ }
+
+ /**
+ * Executes a SELECT statement that returns multiple rows.
+ *
+ * @param sql The SQL
+ * @param args The arguments to be set on the statement.
+ * @return The number of rows impacted or BATCHED_RESULTS if the statements are being batched.
+ * @throws SQLException If statement prepration or execution fails
+ */
+ public List<Map<String, Object>> selectAll(String sql, Object... args) throws SQLException {
+ PreparedStatement ps = connection.prepareStatement(sql);
+ try {
+ setParameters(ps, args);
+ ResultSet rs = ps.executeQuery();
+ return getResults(rs);
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException e) {
+ //ignore
+ }
+ }
+ }
+
+ /**
+ * Executes an INSERT statement.
+ *
+ * @param sql The SQL
+ * @param args The arguments to be set on the statement.
+ * @return The number of rows impacted or BATCHED_RESULTS if the statements are being batched.
+ * @throws SQLException If statement prepration or execution fails
+ */
+ public int insert(String sql, Object... args) throws SQLException {
+ PreparedStatement ps;
+ if (forceGeneratedKeySupport || connection.getMetaData().supportsGetGeneratedKeys()) {
+ ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ } else {
+ ps = connection.prepareStatement(sql);
+ }
+
+ try {
+ setParameters(ps, args);
+ ps.executeUpdate();
+ if (forceGeneratedKeySupport || connection.getMetaData().supportsGetGeneratedKeys()) {
+ List<Map<String, Object>> keys = getResults(ps.getGeneratedKeys());
+ if (keys.size() == 1) {
+ Map<String, Object> key = keys.get(0);
+ Iterator i = key.values().iterator();
+ if (i.hasNext()) {
+ return Integer.parseInt(i.next().toString());
+ }
+ }
+ }
+ return NO_GENERATED_KEY;
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException e) {
+ //ignore
+ }
+ }
+ }
+
+ /**
+ * Executes an UPDATE statement.
+ *
+ * @param sql The SQL
+ * @param args The arguments to be set on the statement.
+ * @return The number of rows impacted or BATCHED_RESULTS if the statements are being batched.
+ * @throws SQLException If statement prepration or execution fails
+ */
+ public int update(String sql, Object... args) throws SQLException {
+ PreparedStatement ps = connection.prepareStatement(sql);
+ try {
+ setParameters(ps, args);
+ return ps.executeUpdate();
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException e) {
+ //ignore
+ }
+ }
+ }
+
+ /**
+ * Executes a DELETE statement.
+ *
+ * @param sql The SQL
+ * @param args The arguments to be set on the statement.
+ * @return The number of rows impacted or BATCHED_RESULTS if the statements are being batched.
+ * @throws SQLException If statement prepration or execution fails
+ */
+ public int delete(String sql, Object... args) throws SQLException {
+ return update(sql, args);
+ }
+
+ /**
+ * Executes any string as a JDBC Statement.
+ * Good for DDL
+ *
+ * @param sql The SQL
+ * @throws SQLException If statement prepration or execution fails
+ */
+ public void run(String sql) throws SQLException {
+ Statement stmt = connection.createStatement();
+ try {
+ stmt.execute(sql);
+ } finally {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ //ignore
+ }
+ }
+ }
+
+ private void setParameters(PreparedStatement ps, Object... args) throws SQLException {
+ for (int i = 0, n = args.length; i < n; i++) {
+ if (args[i] == null) {
+ throw new SQLException("AdHocExecutor requires an instance of Null to represent typed null values for JDBC compatibility");
+ } else if (args[i] instanceof Null) {
+ ((Null) args[i]).getTypeHandler().setParameter(ps, i + 1, null, ((Null) args[i]).getJdbcType());
+ } else {
+ TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(args[i].getClass());
+ if (typeHandler == null) {
+ throw new SQLException("AdHocExecutor could not find a TypeHandler instance for " + args[i].getClass());
+ } else {
+ typeHandler.setParameter(ps, i + 1, args[i], null);
+ }
+ }
+ }
+ }
+
+ private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException {
+ try {
+ List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+ List<String> columns = new ArrayList<String>();
+ List<TypeHandler> typeHandlers = new ArrayList<TypeHandler>();
+ ResultSetMetaData rsmd = rs.getMetaData();
+ for (int i = 0, n = rsmd.getColumnCount(); i < n; i++) {
+ columns.add(rsmd.getColumnLabel(i + 1));
+ try {
+ Class type = Class.forName(rsmd.getColumnClassName(i + 1));
+ TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(type);
+ if (typeHandler == null) {
+ typeHandler = typeHandlerRegistry.getTypeHandler(Object.class);
+ }
+ typeHandlers.add(typeHandler);
+ } catch (Exception e) {
+ typeHandlers.add(typeHandlerRegistry.getTypeHandler(Object.class));
+ }
+ }
+ while (rs.next()) {
+ Map<String, Object> row = new HashMap<String, Object>();
+ for (int i = 0, n = columns.size(); i < n; i++) {
+ String name = columns.get(i);
+ TypeHandler handler = typeHandlers.get(i);
+ row.put(name, handler.getResult(rs, name));
+ }
+ list.add(row);
+ }
+ return list;
+ } finally {
+ try {
+ if (rs != null) rs.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/Null.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/Null.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/Null.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/Null.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,48 @@
+package org.apache.ibatis.adhoc;
+
+import org.apache.ibatis.type.*;
+
+public enum Null {
+ BOOLEAN(new BooleanTypeHandler(), JdbcType.BOOLEAN),
+
+ BYTE(new ByteTypeHandler(), JdbcType.TINYINT),
+ SHORT(new ShortTypeHandler(), JdbcType.SMALLINT),
+ INTEGER(new IntegerTypeHandler(), JdbcType.INTEGER),
+ LONG(new LongTypeHandler(), JdbcType.BIGINT),
+ FLOAT(new FloatTypeHandler(), JdbcType.FLOAT),
+ DOUBLE(new DoubleTypeHandler(), JdbcType.DOUBLE),
+ BIGDECIMAL(new BigDecimalTypeHandler(), JdbcType.DECIMAL),
+
+ STRING(new StringTypeHandler(), JdbcType.VARCHAR),
+ CLOB(new ClobTypeHandler(), JdbcType.CLOB),
+ LONGVARCHAR(new ClobTypeHandler(), JdbcType.LONGVARCHAR),
+
+ BYTEARRAY(new ByteArrayTypeHandler(), JdbcType.LONGVARBINARY),
+ BLOB(new BlobTypeHandler(), JdbcType.BLOB),
+ LONGVARBINARY(new BlobTypeHandler(), JdbcType.LONGVARBINARY),
+
+ OBJECT(new ObjectTypeHandler(), JdbcType.OTHER),
+ OTHER(new ObjectTypeHandler(), JdbcType.OTHER),
+ TIMESTAMP(new DateTypeHandler(), JdbcType.TIMESTAMP),
+ DATE(new DateOnlyTypeHandler(), JdbcType.DATE),
+ TIME(new TimeOnlyTypeHandler(), JdbcType.TIME),
+ SQLTIMESTAMP(new SqlTimestampTypeHandler(), JdbcType.TIMESTAMP),
+ SQLDATE(new SqlDateTypeHandler(), JdbcType.DATE),
+ SQLTIME(new SqlTimeTypeHandler(), JdbcType.TIME);
+
+ private TypeHandler typeHandler;
+ private JdbcType jdbcType;
+
+ private Null(TypeHandler typeHandler, JdbcType jdbcType) {
+ this.typeHandler = typeHandler;
+ this.jdbcType = jdbcType;
+ }
+
+ public TypeHandler getTypeHandler() {
+ return typeHandler;
+ }
+
+ public JdbcType getJdbcType() {
+ return jdbcType;
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/BaseCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/BaseCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/BaseCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/BaseCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,34 @@
+package org.apache.ibatis.cache;
+
+/**
+ * Base Cache class implements a template method pattern for subclasses.
+ */
+public abstract class BaseCache implements Cache {
+
+ protected String id;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object o) {
+ if (getId() == null) throw new RuntimeException("Cache instances require an ID.");
+ if (this == o) return true;
+ if (!(o instanceof BaseCache)) return false;
+
+ BaseCache baseCache = (BaseCache) o;
+
+ if (!getId().equals(baseCache.getId())) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ if (getId() == null) throw new RuntimeException("Cache instances require an ID.");
+ return getId().hashCode();
+ }
+}
\ No newline at end of file
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/Cache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/Cache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/Cache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/Cache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,75 @@
+package org.apache.ibatis.cache;
+
+import org.apache.ibatis.cache.decorators.*;
+import org.apache.ibatis.reflection.MetaObject;
+
+public interface Cache {
+
+ String getId();
+
+ int getSize();
+
+ void putObject(Object key, Object object);
+
+ Object getObject(Object key);
+
+ boolean hasKey(Object key);
+
+ Object removeObject(Object key);
+
+ void clear();
+
+ public class Builder {
+ private String id;
+ private Class implementation;
+ private Integer size;
+ private Long clearInterval;
+ private boolean readWrite;
+
+ public Builder(String id, Class implementation) {
+ this.id = id;
+ this.implementation = implementation;
+ }
+
+ public Builder size(Integer size) {
+ this.size = size;
+ return this;
+ }
+
+ public Builder clearInterval(Long clearInterval) {
+ this.clearInterval = clearInterval;
+ return this;
+ }
+
+ public Builder readWrite(boolean readWrite) {
+ this.readWrite = readWrite;
+ return this;
+ }
+
+ public Cache build() {
+ try {
+ // implementation...
+ Cache cache = (Cache) implementation.newInstance();
+ MetaObject metaCache = MetaObject.forObject(cache);
+ metaCache.setValue("id", id);
+ if (size != null && metaCache.hasSetter("size")) {
+ metaCache.setValue("size", size);
+ }
+ // decorators...
+ if (clearInterval != null) {
+ cache = new ScheduledCache(cache);
+ ((ScheduledCache) cache).setClearInterval(clearInterval);
+ }
+ if (readWrite) {
+ cache = new SerializedCache(cache);
+ }
+ cache = new LoggingCache(cache);
+ cache = new SynchronizedCache(cache);
+ return cache;
+ } catch (Exception e) {
+ throw new RuntimeException("Error building Cache class. Cause: " + e, e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/CacheKey.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/CacheKey.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/CacheKey.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/CacheKey.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,81 @@
+package org.apache.ibatis.cache;
+
+import java.util.*;
+
+public class CacheKey {
+
+ private static final int DEFAULT_MULTIPLYER = 37;
+ private static final int DEFAULT_HASHCODE = 17;
+
+ private int multiplier;
+ private int hashcode;
+ private long checksum;
+ private int count;
+ private List updateList;
+
+ public CacheKey() {
+ this.hashcode = DEFAULT_HASHCODE;
+ this.multiplier = DEFAULT_MULTIPLYER;
+ this.count = 0;
+ this.updateList = new ArrayList();
+ }
+
+ public CacheKey(Object[] objects) {
+ this();
+ updateAll(objects);
+ }
+
+ public void update(Object object) {
+ int baseHashCode = object == null ? 1 : object.hashCode();
+
+ count++;
+ checksum += baseHashCode;
+ baseHashCode *= count;
+
+ hashcode = multiplier * hashcode + baseHashCode;
+
+ updateList.add(object);
+ }
+
+ public void updateAll(Object[] objects) {
+ for (Object o : objects) {
+ update(o);
+ }
+ }
+
+ public boolean equals(Object object) {
+ if (this == object) return true;
+ if (!(object instanceof CacheKey)) return false;
+
+ final CacheKey cacheKey = (CacheKey) object;
+
+ if (hashcode != cacheKey.hashcode) return false;
+ if (checksum != cacheKey.checksum) return false;
+ if (count != cacheKey.count) return false;
+
+ for (int i = 0; i < updateList.size(); i++) {
+ Object thisObject = updateList.get(i);
+ Object thatObject = cacheKey.updateList.get(i);
+ if (thisObject == null) {
+ if (thatObject != null) return false;
+ } else {
+ if (!thisObject.equals(thatObject)) return false;
+ }
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ return hashcode;
+ }
+
+ public String toString() {
+ StringBuffer returnValue = new StringBuffer().append(hashcode).append(':').append(checksum);
+ for (int i = 0; i < updateList.size(); i++) {
+ returnValue.append(':').append(updateList.get(i));
+ }
+
+ return returnValue.toString();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,57 @@
+package org.apache.ibatis.cache.decorators;
+
+import org.apache.ibatis.cache.*;
+import org.apache.ibatis.logging.*;
+
+public class LoggingCache extends BaseCache {
+
+ private static final Log log = LogFactory.getLog(LoggingCache.class);
+
+ private Cache delegate;
+ protected int requests = 0;
+ protected int hits = 0;
+
+ public LoggingCache(Cache delegate) {
+ this.delegate = delegate;
+ }
+
+ public String getId() {
+ return delegate.getId();
+ }
+
+ public int getSize() {
+ return delegate.getSize();
+ }
+
+ public void putObject(Object key, Object object) {
+ delegate.putObject(key, object);
+ }
+
+ public Object getObject(Object key) {
+ requests++;
+ if (hasKey(key)) {
+ hits++;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Cache Hit Ratio [" + getId() + "]: " + getHitRatio());
+ }
+ return delegate.getObject(key);
+ }
+
+ public boolean hasKey(Object key) {
+ return delegate.hasKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ return delegate.removeObject(key);
+ }
+
+ public void clear() {
+ delegate.clear();
+ }
+
+ private double getHitRatio() {
+ return (double) hits / (double) requests;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,76 @@
+package org.apache.ibatis.cache.decorators;
+
+import org.apache.ibatis.cache.*;
+
+public class ScheduledCache extends BaseCache {
+
+ private Cache delegate;
+ protected long clearInterval = 60 * 60 * 1000; // 1 hour
+ protected long lastClear = System.currentTimeMillis();
+
+ public ScheduledCache(Cache delegate) {
+ this.delegate = delegate;
+ }
+
+ public ScheduledCache(Cache delegate, int clearInterval) {
+ this.delegate = delegate;
+ this.clearInterval = clearInterval;
+ }
+
+ public long getClearInterval() {
+ return clearInterval;
+ }
+
+ public void setClearInterval(long clearInterval) {
+ this.clearInterval = clearInterval;
+ }
+
+ public String getId() {
+ return delegate.getId();
+ }
+
+ public int getSize() {
+ clearWhenStale();
+ return delegate.getSize();
+ }
+
+ public void putObject(Object key, Object object) {
+ clearWhenStale();
+ delegate.putObject(key, object);
+ }
+
+ public Object getObject(Object key) {
+ if (clearWhenStale()) {
+ return null;
+ } else {
+ return delegate.getObject(key);
+ }
+ }
+
+ public boolean hasKey(Object key) {
+ if (clearWhenStale()) {
+ return false;
+ } else {
+ return delegate.hasKey(key);
+ }
+ }
+
+ public Object removeObject(Object key) {
+ clearWhenStale();
+ return delegate.removeObject(key);
+ }
+
+ public void clear() {
+ lastClear = System.currentTimeMillis();
+ delegate.clear();
+ }
+
+ private boolean clearWhenStale() {
+ if (System.currentTimeMillis() - lastClear > clearInterval) {
+ clear();
+ return true;
+ }
+ return false;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,75 @@
+package org.apache.ibatis.cache.decorators;
+
+import org.apache.ibatis.cache.*;
+
+import java.io.*;
+
+public class SerializedCache extends BaseCache {
+
+ private Cache delegate;
+
+ public SerializedCache(Cache delegate) {
+ this.delegate = delegate;
+ }
+
+ public String getId() {
+ return delegate.getId();
+ }
+
+ public int getSize() {
+ return delegate.getSize();
+ }
+
+ public void putObject(Object key, Object object) {
+ if (object == null || object instanceof Serializable) {
+ delegate.putObject(key, serialize((Serializable) object));
+ } else {
+ throw new RuntimeException("SharedCache failed to make a copy of a non-serializable object: " + object);
+ }
+ }
+
+ public Object getObject(Object key) {
+ Object object = delegate.getObject(key);
+ return object == null ? null : deserialize((byte[]) object);
+ }
+
+ public boolean hasKey(Object key) {
+ return delegate.hasKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ return delegate.removeObject(key);
+ }
+
+ public void clear() {
+ delegate.clear();
+ }
+
+ private byte[] serialize(Serializable value) {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(value);
+ oos.flush();
+ oos.close();
+ return bos.toByteArray();
+ } catch (Exception e) {
+ throw new RuntimeException("Error serializing object. Cause: " + e, e);
+ }
+ }
+
+ private Serializable deserialize(byte[] value) {
+ Serializable result;
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream((byte[]) value);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ result = (Serializable) ois.readObject();
+ ois.close();
+ } catch (Exception e) {
+ throw new RuntimeException("Error deserializing object. Cause: " + e, e);
+ }
+ return result;
+ }
+
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,41 @@
+package org.apache.ibatis.cache.decorators;
+
+import org.apache.ibatis.cache.*;
+
+public class SynchronizedCache extends BaseCache {
+
+ private Cache delegate;
+
+ public SynchronizedCache(Cache delegate) {
+ this.delegate = delegate;
+ }
+
+ public String getId() {
+ return delegate.getId();
+ }
+
+ public synchronized int getSize() {
+ return delegate.getSize();
+ }
+
+ public synchronized void putObject(Object key, Object object) {
+ delegate.putObject(key, object);
+ }
+
+ public synchronized Object getObject(Object key) {
+ return delegate.getObject(key);
+ }
+
+ public synchronized boolean hasKey(Object key) {
+ return delegate.hasKey(key);
+ }
+
+ public synchronized Object removeObject(Object key) {
+ return delegate.removeObject(key);
+ }
+
+ public synchronized void clear() {
+ delegate.clear();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/FifoCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/FifoCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/FifoCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/FifoCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,51 @@
+package org.apache.ibatis.cache.impl;
+
+import org.apache.ibatis.cache.BaseCache;
+
+import java.util.*;
+
+/**
+ * FIFO (first in, first out) cache controller implementation
+ */
+public class FifoCache extends BaseCache {
+
+ private int size = 256;
+ private Map cache = new HashMap();
+ private List keyList = new LinkedList();
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public void putObject(Object key, Object value) {
+ cache.put(key, value);
+ keyList.add(key);
+ if (keyList.size() > size) {
+ Object oldestKey = keyList.remove(0);
+ cache.remove(oldestKey);
+ }
+ }
+
+ public Object getObject(Object key) {
+ return cache.get(key);
+ }
+
+ public boolean hasKey(Object key) {
+ return cache.containsKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ keyList.remove(key);
+ return cache.remove(key);
+ }
+
+ public void clear() {
+ cache.clear();
+ keyList.clear();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/LruCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/LruCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/LruCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/LruCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,56 @@
+package org.apache.ibatis.cache.impl;
+
+import org.apache.ibatis.cache.BaseCache;
+
+import java.util.*;
+
+/**
+ * LRU (least recently used) cache controller implementation
+ */
+public class LruCache extends BaseCache {
+
+ private int size = 256;
+ private Map cache = new HashMap();
+ private List keyList = new LinkedList();
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public void putObject(Object key, Object value) {
+ cache.put(key, value);
+ keyList.add(key);
+ if (keyList.size() > size) {
+ Object oldestKey = keyList.remove(0);
+ cache.remove(oldestKey);
+ }
+ }
+
+ public Object getObject(Object key) {
+ Object result = cache.get(key);
+ keyList.remove(key);
+ if (result != null) {
+ keyList.add(key);
+ }
+ return result;
+ }
+
+ public boolean hasKey(Object key) {
+ return cache.containsKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ keyList.remove(key);
+ return cache.remove(key);
+ }
+
+ public void clear() {
+ cache.clear();
+ keyList.clear();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/PerpetualCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/PerpetualCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/PerpetualCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/PerpetualCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,35 @@
+package org.apache.ibatis.cache.impl;
+
+import org.apache.ibatis.cache.BaseCache;
+
+import java.util.*;
+
+public class PerpetualCache extends BaseCache {
+
+ private Map cache = new HashMap();
+
+ public int getSize() {
+ return cache.size();
+ }
+
+ public void putObject(Object key, Object value) {
+ cache.put(key, value);
+ }
+
+ public Object getObject(Object key) {
+ return cache.get(key);
+ }
+
+ public boolean hasKey(Object key) {
+ return cache.containsKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ return cache.remove(key);
+ }
+
+ public void clear() {
+ cache.clear();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/SoftCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/SoftCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/SoftCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/SoftCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,39 @@
+package org.apache.ibatis.cache.impl;
+
+import org.apache.ibatis.cache.BaseCache;
+
+import javax.util.SoftHashMap;
+import java.util.Map;
+
+/**
+ * Weak Reference cache implementation
+ */
+public class SoftCache extends BaseCache {
+
+ private Map cache = new SoftHashMap();
+
+ public int getSize() {
+ return cache.size();
+ }
+
+ public void putObject(Object key, Object value) {
+ cache.put(key, value);
+ }
+
+ public Object getObject(Object key) {
+ return cache.get(key);
+ }
+
+ public boolean hasKey(Object key) {
+ return cache.containsKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ return cache.remove(key);
+ }
+
+ public void clear() {
+ cache.clear();
+ }
+
+}
\ No newline at end of file
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/WeakCache.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/WeakCache.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/WeakCache.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/cache/impl/WeakCache.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,38 @@
+package org.apache.ibatis.cache.impl;
+
+import org.apache.ibatis.cache.BaseCache;
+
+import java.util.*;
+
+/**
+ * Weak Reference cache implementation
+ */
+public class WeakCache extends BaseCache {
+
+ private Map cache = new WeakHashMap();
+
+ public int getSize() {
+ return cache.size();
+ }
+
+ public void putObject(Object key, Object value) {
+ cache.put(key, value);
+ }
+
+ public Object getObject(Object key) {
+ return cache.get(key);
+ }
+
+ public boolean hasKey(Object key) {
+ return cache.containsKey(key);
+ }
+
+ public Object removeObject(Object key) {
+ return cache.remove(key);
+ }
+
+ public void clear() {
+ cache.clear();
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BaseExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BaseExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BaseExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BaseExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,186 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.cache.impl.PerpetualCache;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.logging.jdbc.ConnectionLogger;
+import org.apache.ibatis.mapping.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+
+import java.sql.*;
+import java.util.*;
+
+public abstract class BaseExecutor implements Executor {
+
+ private static final Log log = LogFactory.getLog(BaseExecutor.class);
+ private static final Object EXECUTION_PLACEHOLDER = new Object();
+
+ protected final Connection connection;
+
+ protected final List<DeferredLoad> deferredLoads;
+ protected final PerpetualCache localCache;
+
+ protected int queryStack = 0;
+
+ protected List<BatchResult> batchResults = new ArrayList<BatchResult>();
+
+ protected BaseExecutor(Connection connection) {
+ if (log.isDebugEnabled()) {
+ this.connection = ConnectionLogger.newInstance(connection);
+ } else {
+ this.connection = connection;
+ }
+ this.deferredLoads = new ArrayList<DeferredLoad>();
+ this.localCache = new PerpetualCache();
+ }
+
+ public Connection getConnection() {
+ return connection;
+ }
+
+ public void close() {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ // Ignore. There's nothing that can be done at this point.
+ }
+ }
+
+ public int update(MappedStatement ms, Object parameter) throws SQLException {
+ localCache.clear();
+ return doUpdate(ms, parameter);
+ }
+
+ public List flushStatements() throws SQLException {
+ batchResults.addAll(doFlushStatements());
+ return batchResults;
+ }
+
+ public List query(MappedStatement ms, Object parameter, int offset, int limit, ResultHandler resultHandler) throws SQLException {
+ List list;
+ try {
+ queryStack++;
+ CacheKey key = createCacheKey(ms, parameter, offset, limit);
+ if (localCache.hasKey(key)) {
+ list = (List) localCache.getObject(key);
+ } else {
+ localCache.putObject(key, EXECUTION_PLACEHOLDER);
+ try {
+ list = doQuery(ms, parameter, offset, limit, resultHandler);
+ } finally {
+ localCache.removeObject(key);
+ }
+ localCache.putObject(key, list);
+ }
+ } finally {
+ queryStack--;
+ }
+ if (queryStack == 0) {
+ for (DeferredLoad deferredLoad : deferredLoads) {
+ deferredLoad.load();
+ }
+ }
+ return list;
+ }
+
+ public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key) {
+ deferredLoads.add(new DeferredLoad(ms, resultObject, property, key));
+ }
+
+ public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, int offset, int limit) {
+ CacheKey cacheKey = new CacheKey();
+ cacheKey.update(ms.getId());
+ cacheKey.update(offset);
+ cacheKey.update(limit);
+ if (ms.getDynamicParameterMappings(parameterObject).size() > 0 && parameterObject != null) {
+ TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
+ if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+ cacheKey.update(parameterObject);
+ } else {
+ MetaObject metaObject = MetaObject.forObject(parameterObject);
+ List<ParameterMapping> parameterMappings = ms.getDynamicParameterMappings(parameterObject);
+ for (ParameterMapping parameterMapping : parameterMappings) {
+ cacheKey.update(metaObject.getValue(parameterMapping.getProperty()));
+ }
+ }
+ }
+ return cacheKey;
+ }
+
+ public boolean isCached(MappedStatement ms, CacheKey key) {
+ return localCache.hasKey(key);
+ }
+
+ public void commit(boolean required) throws SQLException {
+ flushStatements();
+ if (required) {
+ connection.commit();
+ }
+ }
+
+ public void rollback(boolean required) throws SQLException {
+ if (required) {
+ connection.rollback();
+ }
+ }
+
+ protected abstract int doUpdate(MappedStatement ms, Object parameter)
+ throws SQLException;
+
+ protected abstract List<BatchResult> doFlushStatements()
+ throws SQLException;
+
+ protected abstract List doQuery(MappedStatement ms, Object parameter, int offset, int limit, ResultHandler resultHandler)
+ throws SQLException;
+
+ protected void closeStatement(Statement statement) {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+ }
+
+ private class DeferredLoad {
+
+ MappedStatement mappedStatement;
+ private MetaObject resultObject;
+ private String property;
+ private CacheKey key;
+
+ public DeferredLoad(MappedStatement mappedStatement, MetaObject resultObject, String property, CacheKey key) {
+ this.mappedStatement = mappedStatement;
+ this.resultObject = resultObject;
+ this.property = property;
+ this.key = key;
+ }
+
+ public void load() {
+ Object value = null;
+ List list = (List) localCache.getObject(key);
+ Class targetType = resultObject.getSetterType(property);
+ if (Set.class.isAssignableFrom(targetType)) {
+ value = new HashSet(list);
+ } else if (Collection.class.isAssignableFrom(targetType)) {
+ value = list;
+ } else if (targetType.isArray()) {
+ Object array = java.lang.reflect.Array.newInstance(targetType.getComponentType(), list.size());
+ value = list.toArray((Object[]) array);
+ } else {
+ if (list.size() > 1) {
+ throw new RuntimeException("Statement returned more than one row, where no more than one was expected.");
+ } else if (list.size() == 1) {
+ value = list.get(0);
+ }
+ }
+ resultObject.setValue(property, value);
+ }
+
+ }
+
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,93 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.mapping.Configuration;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.*;
+
+import java.sql.*;
+import java.util.*;
+
+public class BatchExecutor extends BaseExecutor {
+
+ public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;
+
+ private final List<Statement> statementList = new ArrayList<Statement>();
+ private final List<BatchResult> batchResultList = new ArrayList<BatchResult>();
+ private String currentSql;
+
+ public BatchExecutor(Connection connection) {
+ super(connection);
+ }
+
+ public int doUpdate(MappedStatement ms, Object parameterObject)
+ throws SQLException {
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, Executor.NO_ROW_OFFSET, Executor.NO_ROW_LIMIT, null);
+ String sql = handler.getSql();
+ Statement stmt;
+ if (currentSql != null && sql.hashCode() == currentSql.hashCode() && sql.length() == currentSql.length()) {
+ int last = statementList.size() - 1;
+ stmt = statementList.get(last);
+ } else {
+ stmt = handler.prepare(connection);
+ currentSql = sql;
+ statementList.add(stmt);
+ batchResultList.add(new BatchResult(ms, sql, parameterObject));
+ }
+ handler.parameterize(stmt);
+ handler.batch(stmt);
+ return BATCH_UPDATE_RETURN_VALUE;
+ }
+
+ public List doQuery(MappedStatement ms, Object parameterObject, int rowOffset, int rowLimit, ResultHandler resultHandler)
+ throws SQLException {
+ flushStatements();
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, rowOffset, rowLimit, resultHandler);
+ Statement stmt = handler.prepare(connection);
+ handler.parameterize(stmt);
+ return handler.query(stmt, resultHandler);
+ }
+
+ public List<BatchResult> doFlushStatements() throws SQLException {
+ List<BatchResult> results = new ArrayList<BatchResult>();
+ try {
+ for (int i = 0, n = statementList.size(); i < n; i++) {
+ Statement stmt = statementList.get(i);
+ BatchResult batchResult = batchResultList.get(i);
+ try {
+ batchResult.setUpdateCounts(stmt.executeBatch());
+ } catch (BatchUpdateException e) {
+ StringBuffer message = new StringBuffer();
+ message.append(batchResult.getMappedStatement().getId())
+ .append(" (batch index #")
+ .append(i + 1)
+ .append(")")
+ .append(" failed.");
+ if (i > 0) {
+ message.append(" ")
+ .append(i)
+ .append(" prior sub executor(s) completed successfully, but will be rolled back.");
+ }
+ throw new BatchExecutorException(message.toString(), e, results, batchResult);
+ }
+ results.add(batchResult);
+ }
+ return results;
+ } finally {
+ for (Statement stmt : statementList) {
+ closeStatement(stmt);
+ }
+ currentSql = null;
+ statementList.clear();
+ batchResultList.clear();
+ }
+ }
+
+}
+
+
+
+
+
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutorException.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutorException.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutorException.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchExecutorException.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,62 @@
+package org.apache.ibatis.executor;
+
+import java.sql.BatchUpdateException;
+import java.util.List;
+
+public class BatchExecutorException extends RuntimeException {
+
+ private final List successfulBatchResults;
+ private final BatchUpdateException batchUpdateException;
+ private final BatchResult batchResult;
+
+ public BatchExecutorException(String message, BatchUpdateException cause, List successfulBatchResults,
+ BatchResult batchResult) {
+ super(message + " Cause: " + cause, cause);
+ this.batchUpdateException = cause;
+ this.successfulBatchResults = successfulBatchResults;
+ this.batchResult = batchResult;
+ }
+
+ /**
+ * Returns the BatchUpdateException that caused the nested executor
+ * to fail. That exception contains an array of row counts
+ * that can be used to determine exactly which statemtn of the
+ * executor caused the failure (or failures).
+ *
+ * @return the root BatchUpdateException
+ */
+ public BatchUpdateException getBatchUpdateException() {
+ return batchUpdateException;
+ }
+
+ /**
+ * Returns a list of BatchResult objects. There will be one entry
+ * in the list for each successful sub-executor executed before the failing
+ * executor.
+ *
+ * @return the previously successful executor results (may be an empty list
+ * if no executor has executed successfully)
+ */
+ public List getSuccessfulBatchResults() {
+ return successfulBatchResults;
+ }
+
+ /**
+ * Returns the SQL statement that caused the failure
+ * (not the parameterArray)
+ *
+ * @return the failing SQL string
+ */
+ public String getFailingSqlStatement() {
+ return batchResult.getSql();
+ }
+
+ /**
+ * Returns the statement id of the statement that caused the failure
+ *
+ * @return the statement id
+ */
+ public String getFailingStatementId() {
+ return batchResult.getMappedStatement().getId();
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchResult.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchResult.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchResult.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/BatchResult.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,40 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.mapping.MappedStatement;
+
+public class BatchResult {
+
+ private final MappedStatement mappedStatement;
+ private final String sql;
+ private final Object parameterObject;
+
+ private int[] updateCounts;
+
+ public BatchResult(MappedStatement mappedStatement, String sql, Object parameterObject) {
+ super();
+ this.mappedStatement = mappedStatement;
+ this.sql = sql;
+ this.parameterObject = parameterObject;
+ }
+
+ public MappedStatement getMappedStatement() {
+ return mappedStatement;
+ }
+
+ public String getSql() {
+ return sql;
+ }
+
+ public Object getParameterObject() {
+ return parameterObject;
+ }
+
+ public int[] getUpdateCounts() {
+ return updateCounts;
+ }
+
+ public void setUpdateCounts(int[] updateCounts) {
+ this.updateCounts = updateCounts;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/CachingExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/CachingExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/CachingExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/CachingExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,116 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.cache.*;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.reflection.MetaObject;
+
+import java.sql.*;
+import java.util.*;
+
+public class CachingExecutor implements Executor {
+
+ private Executor delegate;
+
+ private Set<Cache> clearCaches;
+ private List<CacheEntry> cacheEntries;
+
+ public CachingExecutor(Executor delegate) {
+ this.delegate = delegate;
+ }
+
+ public Connection getConnection() {
+ return delegate.getConnection();
+ }
+
+ public void close() {
+ delegate.close();
+ }
+
+ public int update(MappedStatement ms, Object parameterObject) throws SQLException {
+ Cache cache = ms.getCache();
+ if (cache != null) {
+ if (clearCaches == null) {
+ clearCaches = new HashSet<Cache>();
+ }
+ clearCaches.add(cache);
+ }
+ return delegate.update(ms, parameterObject);
+ }
+
+ public List query(MappedStatement ms, Object parameterObject, int offset, int limit, ResultHandler resultHandler) throws SQLException {
+ Cache cache = ms.getCache();
+ if (cache != null) {
+ synchronized (cache) {
+ CacheKey key = createCacheKey(ms, parameterObject, offset, limit);
+ if (cache.hasKey(key)) {
+ return (List) cache.getObject(key);
+ } else {
+ List list = delegate.query(ms, parameterObject, offset, limit, resultHandler);
+ if (cacheEntries == null) {
+ cacheEntries = new ArrayList<CacheEntry>();
+ }
+ cacheEntries.add(new CacheEntry(cache, key, list));
+ return list;
+ }
+ }
+ } else {
+ return delegate.query(ms, parameterObject, offset, limit, resultHandler);
+ }
+ }
+
+ public List flushStatements() throws SQLException {
+ return delegate.flushStatements();
+ }
+
+ public void commit(boolean required) throws SQLException {
+ if (clearCaches != null) {
+ for (Cache cache : clearCaches) {
+ cache.clear();
+ }
+ clearCaches.clear();
+ }
+ if (cacheEntries != null) {
+ for (CacheEntry entry : cacheEntries) {
+ entry.commit();
+ }
+ cacheEntries.clear();
+ }
+ delegate.commit(required);
+ }
+
+ public void rollback(boolean required) throws SQLException {
+ if (clearCaches != null) clearCaches.clear();
+ if (cacheEntries != null) cacheEntries.clear();
+ delegate.rollback(required);
+ }
+
+ public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, int offset, int limit) {
+ return delegate.createCacheKey(ms, parameterObject, offset, limit);
+ }
+
+ public boolean isCached(MappedStatement ms, CacheKey key) {
+ throw new UnsupportedOperationException("The CachingExecutor should not be used by result loaders and thus isCached() should never be called.");
+ }
+
+ public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key) {
+ throw new UnsupportedOperationException("The CachingExecutor should not be used by result loaders and thus deferLoad() should never be called.");
+ }
+
+ private static class CacheEntry {
+ private Cache cache;
+ private CacheKey key;
+ private Object value;
+
+ public CacheEntry(Cache cache, CacheKey key, Object value) {
+ this.cache = cache;
+ this.key = key;
+ this.value = value;
+ }
+
+ public void commit() {
+ cache.putObject(key, value);
+ }
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ErrorContext.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ErrorContext.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ErrorContext.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ErrorContext.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,84 @@
+package org.apache.ibatis.executor;
+
+public class ErrorContext {
+
+ private String resource;
+ private String activity;
+ private String objectId;
+ private String moreInfo;
+ private Throwable cause;
+
+ public void set(String resource, String activity, String objectId, String moreInfo) {
+ this.resource = resource;
+ this.activity = activity;
+ this.objectId = objectId;
+ this.moreInfo = moreInfo;
+ }
+
+ public void set(String activity, String objectId, String moreInfo) {
+ this.activity = activity;
+ this.objectId = objectId;
+ this.moreInfo = moreInfo;
+ }
+
+ public void set(String objectId, String moreInfo) {
+ this.objectId = objectId;
+ this.moreInfo = moreInfo;
+ }
+
+ public void set(String moreInfo) {
+ this.moreInfo = moreInfo;
+ }
+
+ public void set(Throwable cause) {
+ this.cause = cause;
+ }
+
+ public String toString() {
+ StringBuffer message = new StringBuffer();
+
+ // resource
+ if (resource != null) {
+ message.append(" \n*** The error occurred in ");
+ message.append(resource);
+ message.append(".");
+ }
+
+ // activity
+ if (activity != null) {
+ message.append(" \n*** The error occurred while ");
+ message.append(activity);
+ message.append(".");
+ }
+
+ // object
+ if (objectId != null) {
+ message.append(" \n*** Check ");
+ message.append(objectId);
+ message.append(".");
+ }
+
+ // more info
+ if (moreInfo != null) {
+ message.append(" \n*** ");
+ message.append(moreInfo);
+ }
+
+ // cause
+ if (cause != null) {
+ message.append(" \n*** Cause: ");
+ message.append(cause.toString());
+ }
+
+ return message.toString();
+ }
+
+ public void reset() {
+ resource = null;
+ activity = null;
+ objectId = null;
+ moreInfo = null;
+ cause = null;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/Executor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/Executor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/Executor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/Executor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,37 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.reflection.MetaObject;
+
+import java.sql.*;
+import java.util.List;
+
+public interface Executor {
+
+ int NO_ROW_OFFSET = 0;
+ int NO_ROW_LIMIT = Integer.MAX_VALUE;
+ ResultHandler NO_RESULT_HANDLER = null;
+
+ int update(MappedStatement ms, Object parameter) throws SQLException;
+
+ List query(MappedStatement ms, Object parameter, int offset, int limit, ResultHandler resultHandler) throws SQLException;
+
+ List<BatchResult> flushStatements() throws SQLException;
+
+ void commit(boolean required) throws SQLException;
+
+ void rollback(boolean required) throws SQLException;
+
+ CacheKey createCacheKey(MappedStatement ms, Object parameterObject, int offset, int limit);
+
+ boolean isCached(MappedStatement ms, CacheKey key);
+
+ void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key);
+
+ Connection getConnection();
+
+ void close();
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ReuseExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ReuseExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ReuseExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/ReuseExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,68 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.mapping.Configuration;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.*;
+
+import java.sql.*;
+import java.util.*;
+
+public class ReuseExecutor extends BaseExecutor {
+
+ private final Map<String, Statement> statementMap = new HashMap<String, Statement>();
+
+ public ReuseExecutor(Connection connection) {
+ super(connection);
+ }
+
+ public int doUpdate(MappedStatement ms, Object parameter)
+ throws SQLException {
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, Executor.NO_ROW_OFFSET, Executor.NO_ROW_LIMIT, null);
+ Statement stmt = prepareStatement(handler);
+ return handler.update(stmt);
+ }
+
+ public List doQuery(MappedStatement ms, Object parameter, int rowOffset, int rowLimit, ResultHandler resultHandler) throws SQLException {
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowOffset, rowLimit, resultHandler);
+ Statement stmt = prepareStatement(handler);
+ return handler.query(stmt, resultHandler);
+ }
+
+ public List doFlushStatements()
+ throws SQLException {
+ for (Statement stmt : statementMap.values()) {
+ closeStatement(stmt);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ private Statement prepareStatement(StatementHandler handler)
+ throws SQLException {
+ Statement stmt;
+ String sql = handler.getSql();
+ if (hasStatementFor(sql)) {
+ stmt = getStatement(sql);
+ } else {
+ stmt = handler.prepare(connection);
+ putStatement(sql, stmt);
+ }
+ handler.parameterize(stmt);
+ return stmt;
+ }
+
+ private boolean hasStatementFor(String sql) {
+ return statementMap.keySet().contains(sql);
+ }
+
+ private Statement getStatement(String s) {
+ return statementMap.get(s);
+ }
+
+ private void putStatement(String sql, Statement stmt) {
+ statementMap.put(sql, stmt);
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/SimpleExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/SimpleExecutor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/SimpleExecutor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/SimpleExecutor.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,54 @@
+package org.apache.ibatis.executor;
+
+import org.apache.ibatis.mapping.Configuration;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.*;
+
+import java.sql.*;
+import java.util.*;
+
+public class SimpleExecutor extends BaseExecutor {
+
+ public SimpleExecutor(Connection connection) {
+ super(connection);
+ }
+
+ public int doUpdate(MappedStatement ms, Object parameter)
+ throws SQLException {
+ Statement stmt = null;
+ try {
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, Executor.NO_ROW_OFFSET, Executor.NO_ROW_LIMIT, null);
+ stmt = prepareStatement(handler);
+ return handler.update(stmt);
+ } finally {
+ closeStatement(stmt);
+ }
+ }
+
+ public List doQuery(MappedStatement ms, Object parameter, int rowOffset, int rowLimit, ResultHandler resultHandler) throws SQLException {
+ Statement stmt = null;
+ try {
+ Configuration configuration = ms.getConfiguration();
+ StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowOffset, rowLimit, resultHandler);
+ stmt = prepareStatement(handler);
+ return handler.query(stmt, resultHandler);
+ } finally {
+ closeStatement(stmt);
+ }
+ }
+
+ public List doFlushStatements()
+ throws SQLException {
+ return Collections.EMPTY_LIST;
+ }
+
+ private Statement prepareStatement(StatementHandler handler) throws SQLException {
+ Statement stmt;
+ stmt = handler.prepare(connection);
+ handler.parameterize(stmt);
+ return stmt;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,57 @@
+package org.apache.ibatis.executor.loader;
+
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.MappedStatement;
+
+import java.sql.SQLException;
+import java.util.*;
+
+public class ResultLoader {
+
+ protected static final Class[] LIST_INTERFACES = new Class[]{List.class};
+ protected static final Class[] SET_INTERFACES = new Class[]{Set.class};
+
+ protected final Executor executor;
+ protected final MappedStatement mappedStatement;
+ protected final Object parameterObject;
+ protected final Class targetType;
+
+ protected boolean loaded;
+ protected Object resultObject;
+
+ public ResultLoader(Executor executor, MappedStatement mappedStatement, Object parameterObject, Class targetType) {
+ this.executor = executor;
+ this.mappedStatement = mappedStatement;
+ this.parameterObject = parameterObject;
+ this.targetType = targetType;
+ }
+
+ public Object loadResult() throws SQLException {
+ List list = executor.query(mappedStatement, parameterObject, Executor.NO_ROW_OFFSET, Executor.NO_ROW_LIMIT, Executor.NO_RESULT_HANDLER);
+ if (targetType != null && Set.class.isAssignableFrom(targetType)) {
+ resultObject = new HashSet(list);
+ } else if (targetType != null && Collection.class.isAssignableFrom(targetType)) {
+ resultObject = list;
+ } else if (targetType != null && targetType.isArray()) {
+ resultObject = listToArray(list, targetType.getComponentType());
+ } else {
+ if (list.size() > 1) {
+ throw new RuntimeException("Statement " + mappedStatement.getId() + " returned more than one row, where no more than one was expected.");
+ } else if (list.size() == 1) {
+ resultObject = list.get(0);
+ }
+ }
+ return resultObject;
+ }
+
+ public boolean wasNull() {
+ return resultObject == null;
+ }
+
+ private Object[] listToArray(List list, Class type) {
+ Object array = java.lang.reflect.Array.newInstance(type, list.size());
+ array = list.toArray((Object[]) array);
+ return (Object[]) array;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,59 @@
+package org.apache.ibatis.executor.loader;
+
+import org.apache.ibatis.reflection.MetaObject;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.util.*;
+
+public class ResultLoaderRegistry implements Serializable {
+
+ private final Map<String, LoadPair> loaderMap = new HashMap<String, LoadPair>();
+
+ public void registerLoader(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
+ // Converts property to method name strictly for performance.
+ String upperFirst = getUppercaseFirstProperty(property);
+ loaderMap.put(toGetter(upperFirst), new LoadPair(property, metaResultObject, resultLoader));
+ loaderMap.put(toSetter(upperFirst), new LoadPair(property, metaResultObject, resultLoader));
+ }
+
+ public boolean loadByMethod(String methodName) throws SQLException {
+ synchronized (loaderMap) {
+ ResultLoaderRegistry.LoadPair pair = loaderMap.remove(methodName.toUpperCase());
+ if (pair != null) {
+ pair.load();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private String toGetter(String first) {
+ return "GET" + first;
+ }
+
+ private String toSetter(String first) {
+ return "SET" + first;
+ }
+
+ private static String getUppercaseFirstProperty(String property) {
+ String[] parts = property.split("\\.");
+ return parts[0].toUpperCase();
+ }
+
+ private class LoadPair {
+ private String property;
+ private MetaObject metaResultObject;
+ private ResultLoader resultLoader;
+
+ private LoadPair(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
+ this.property = property;
+ this.metaResultObject = metaResultObject;
+ this.resultLoader = resultLoader;
+ }
+
+ public void load() throws SQLException {
+ metaResultObject.setValue(property, resultLoader.loadResult());
+ }
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,47 @@
+package org.apache.ibatis.executor.loader;
+
+import net.sf.cglib.proxy.*;
+import org.apache.ibatis.reflection.*;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+public class ResultObjectProxy {
+
+ public static Object createProxy(Class type, Object target, ResultLoaderRegistry lazyLoader) {
+ return EnhancedResultObjectProxyImpl.createProxy(type, target, lazyLoader);
+ }
+
+ private static class EnhancedResultObjectProxyImpl implements InvocationHandler, Serializable {
+
+ private Object target;
+ private ResultLoaderRegistry lazyLoader;
+
+ private EnhancedResultObjectProxyImpl(Object target, ResultLoaderRegistry lazyLoader) {
+ this.target = target;
+ this.lazyLoader = lazyLoader;
+ }
+
+ public static Object createProxy(Class type, Object target, ResultLoaderRegistry lazyLoader) {
+ return Enhancer.create(type, new EnhancedResultObjectProxyImpl(target, lazyLoader));
+ }
+
+ public Object invoke(Object o, Method method, Object[] args) throws Throwable {
+ try {
+ Object value = method.invoke(target, args);
+ if (value == null) {
+ String methodName = method.getName();
+ if (PropertyNamer.isProperty(methodName)) {
+ if (lazyLoader.loadByMethod(methodName)) {
+ value = method.invoke(target, args);
+ }
+ }
+ }
+ return value;
+ } catch (Throwable t) {
+ throw ExceptionUtil.unwrapThrowable(t);
+ }
+ }
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/DefaultParameterHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/DefaultParameterHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/DefaultParameterHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/DefaultParameterHandler.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,53 @@
+package org.apache.ibatis.executor.parameter;
+
+import org.apache.ibatis.mapping.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.type.*;
+
+import java.sql.*;
+import java.util.List;
+
+public class DefaultParameterHandler implements ParameterHandler {
+
+ private final TypeHandlerRegistry typeHandlerRegistry;
+
+ private final MappedStatement mappedStatement;
+ private final Object parameterObject;
+
+ public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject) {
+ this.mappedStatement = mappedStatement;
+ this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
+ this.parameterObject = parameterObject;
+ }
+
+ public Object getParameterObject() {
+ return parameterObject;
+ }
+
+ public void setParameters(PreparedStatement ps)
+ throws SQLException {
+ List<ParameterMapping> parameterMappings = mappedStatement.getDynamicParameterMappings(parameterObject);
+ if (parameterMappings != null) {
+ MetaObject metaObject = parameterObject == null ? null : MetaObject.forObject(parameterObject);
+ for (int i = 0; i < parameterMappings.size(); i++) {
+ ParameterMapping parameterMapping = parameterMappings.get(i);
+ if (parameterMapping.getMode() != ParameterMode.OUT) {
+ Object value;
+ if (parameterObject == null) {
+ value = null;
+ } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+ value = parameterObject;
+ } else {
+ value = metaObject == null ? null : metaObject.getValue(parameterMapping.getProperty());
+ }
+ TypeHandler typeHandler = parameterMapping.getTypeHandler();
+ if (typeHandler == null) {
+ throw new RuntimeException("There was no TypeHandler found for parameter " + parameterMapping.getProperty() + " of statement " + mappedStatement.getId());
+ }
+ typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
+ }
+ }
+ }
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/ParameterHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/ParameterHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/ParameterHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/parameter/ParameterHandler.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,12 @@
+package org.apache.ibatis.executor.parameter;
+
+import java.sql.*;
+
+public interface ParameterHandler {
+
+ Object getParameterObject();
+
+ void setParameters(PreparedStatement ps)
+ throws SQLException;
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/DefaultResultHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/DefaultResultHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/DefaultResultHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/DefaultResultHandler.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,17 @@
+package org.apache.ibatis.executor.result;
+
+import java.util.*;
+
+public class DefaultResultHandler implements ResultHandler {
+
+ private final List list = new ArrayList();
+
+ public void handleResult(Object resultObject) {
+ list.add(resultObject);
+ }
+
+ public List getResultList() {
+ return list;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/ResultHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/ResultHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/ResultHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/executor/result/ResultHandler.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,7 @@
+package org.apache.ibatis.executor.result;
+
+public interface ResultHandler {
+
+ void handleResult(Object resultObject);
+
+}