From e24439984b6af275ecef7d3f5da8b8f92e14bd59 Mon Sep 17 00:00:00 2001 From: "Richard G. Curtis" Date: Fri, 9 Dec 2011 16:30:58 +0000 Subject: [PATCH] OPENJPA-2068: Optimized calendar creation. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1212503 13f79535-47bb-0310-9956-ffa450edef68 --- .../kernel/InstanceResultObjectProvider.java | 7 ++++- .../apache/openjpa/jdbc/sql/DBDictionary.java | 23 ++++++++++---- .../openjpa/kernel/ResultShapePacker.java | 16 ++++++++++ .../openjpa/kernel/SingleFieldManager.java | 31 ++++++++++++------- .../openjpa/jdbc/meta/TestCalendarField.java | 25 +++++++++++++-- .../persistence/relations/LRSEntity.java | 9 ++++-- 6 files changed, 86 insertions(+), 25 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java index cf2b3e346..93f3c7672 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java @@ -24,6 +24,7 @@ import org.apache.openjpa.jdbc.meta.ClassMapping; import org.apache.openjpa.jdbc.sql.Result; import org.apache.openjpa.jdbc.sql.Select; import org.apache.openjpa.jdbc.sql.SelectExecutor; +import org.apache.openjpa.util.ProxyCalendar; /** * Object provider implementation wrapped around a {@link Select}. @@ -56,6 +57,10 @@ public class InstanceResultObjectProvider ClassMapping mapping = res.getBaseMapping(); if (mapping == null) mapping = _mapping; - return res.load(mapping, getStore(), getFetchConfiguration()); + Object ret = res.load(mapping, getStore(), getFetchConfiguration()); + if (ret != null && ret instanceof ProxyCalendar) { + ret = ((ProxyCalendar) ret).copy(ret); + } + return ret; } } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java index 07df88169..cbd09dd86 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java @@ -44,6 +44,7 @@ import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; +import java.text.DateFormatSymbols; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -51,6 +52,7 @@ import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -59,6 +61,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.TimeZone; +import java.util.spi.TimeZoneNameProvider; import javax.sql.DataSource; @@ -118,6 +122,7 @@ import org.apache.openjpa.util.ObjectExistsException; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.OptimisticException; +import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.QueryException; import org.apache.openjpa.util.ReferentialIntegrityException; import org.apache.openjpa.util.Serialization; @@ -420,7 +425,9 @@ public class DBDictionary public final Map> sqlStateCodes = new HashMap>(); - + + protected ProxyManager _proxyManager; + public DBDictionary() { fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{ "BIGINT", "BIT", "BLOB", "CLOB", "DATE", "DECIMAL", "DISTINCT", @@ -692,17 +699,22 @@ public class DBDictionary * Convert the specified column of the SQL ResultSet to the proper * java type. Converts the date from a {@link Timestamp} by default. */ - public Calendar getCalendar(ResultSet rs, int column) - throws SQLException { + public Calendar getCalendar(ResultSet rs, int column) throws SQLException { Date d = getDate(rs, column); if (d == null) return null; - - Calendar cal = Calendar.getInstance(); + Calendar cal = (Calendar) getProxyManager().newCalendarProxy(GregorianCalendar.class, null); cal.setTime(d); return cal; } + private ProxyManager getProxyManager() { + if (_proxyManager == null) { + _proxyManager = conf.getProxyManagerInstance(); + } + return _proxyManager; + } + /** * Convert the specified column of the SQL ResultSet to the proper * java type. @@ -5540,5 +5552,4 @@ public class DBDictionary public String getIdentityColumnName() { return null; } - } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShapePacker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShapePacker.java index 046fdd799..ac1302cee 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShapePacker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShapePacker.java @@ -18,6 +18,10 @@ */ package org.apache.openjpa.kernel; +import java.util.Calendar; + +import org.apache.openjpa.util.ProxyCalendar; + /** * Packs result by delegation to a ResultShape. @@ -43,6 +47,18 @@ public class ResultShapePacker extends ResultPacker { @Override public Object pack(Object[] values) { + // Check for proxied calenders and cleanup if any are found. + if (_types != null) { + for (Class t : _types) { + if (t.equals(Calendar.class)) { + for (int i = 0; i < values.length; i++) { + if (values[i] instanceof ProxyCalendar) { + values[i] = ((ProxyCalendar) values[i]).copy((ProxyCalendar) values[i]); + } + } + } + } + } if (_shape == null) return super.pack(values); return _shape.pack(values, _types, _aliases); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java index 19ade48b2..fea715786 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.Map; +import java.util.TimeZone; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.enhance.PersistenceCapable; @@ -77,31 +78,34 @@ class SingleFieldManager extends TransferFieldManager implements Serializable { case JavaTypes.DATE: if (objval == null) return false; - proxy = checkProxy(); + proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); ((Date) proxy).setTime(((Date) objval).getTime()); - if (proxy instanceof Timestamp - && objval instanceof Timestamp) - ((Timestamp) proxy).setNanos(((Timestamp) objval). - getNanos()); + if (proxy instanceof Timestamp && objval instanceof Timestamp) + ((Timestamp) proxy).setNanos(((Timestamp) objval).getNanos()); ret = true; } break; case JavaTypes.CALENDAR: if (objval == null) return false; - proxy = checkProxy(); + proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); ((Calendar) proxy).setTime(((Calendar) objval).getTime()); ret = true; + } else { + Object init = fmd.getInitializer(); + if (init != null && init instanceof TimeZone) { + ((Calendar) proxy).setTimeZone((TimeZone)init); + } } break; case JavaTypes.COLLECTION: if (objval == null && !replaceNull) return false; - proxy = checkProxy(); + proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); if (objval != null) @@ -112,7 +116,7 @@ class SingleFieldManager extends TransferFieldManager implements Serializable { case JavaTypes.MAP: if (objval == null && !replaceNull) return false; - proxy = checkProxy(); + proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); if (objval != null) @@ -123,7 +127,7 @@ class SingleFieldManager extends TransferFieldManager implements Serializable { case JavaTypes.OBJECT: if (objval == null) return false; - proxy = checkProxy(); + proxy = checkProxy(fmd); if (proxy == null) { proxy = getProxyManager().newCustomProxy(objval, _sm.getBroker().getConfiguration(). @@ -152,13 +156,16 @@ class SingleFieldManager extends TransferFieldManager implements Serializable { /** * If the current field is a usable proxy, return it; else return null. */ - private Proxy checkProxy() { + private Proxy checkProxy(FieldMetaData fmd) { if (!(objval instanceof Proxy)) return null; Proxy proxy = (Proxy) objval; - if (proxy.getOwner() == null || Proxies.isOwner(proxy, _sm, field)) - return proxy; + if (proxy.getOwner() == null || Proxies.isOwner(proxy, _sm, field)) { + if(fmd.getProxyType().isAssignableFrom(proxy.getClass())){ + return proxy; + } + } return null; } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/TestCalendarField.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/TestCalendarField.java index 0dfe9d826..86022039d 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/TestCalendarField.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/TestCalendarField.java @@ -20,14 +20,13 @@ package org.apache.openjpa.jdbc.meta; import java.io.IOException; import java.sql.SQLException; - import java.util.Calendar; +import java.util.List; import java.util.TimeZone; -import org.apache.openjpa.persistence.OpenJPAPersistence; -import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.simple.TemporalFieldTypes; import org.apache.openjpa.persistence.test.SingleEMTestCase; +import org.apache.openjpa.util.ProxyCalendar; public class TestCalendarField extends SingleEMTestCase { @@ -54,4 +53,24 @@ public class TestCalendarField extends SingleEMTestCase { tft = find(TemporalFieldTypes.class).get(0); assertEquals(tz, tft.getCalendarTimeZoneField().getTimeZone()); } + + + public void testCalendarQuery() throws Exception { + persist(new TemporalFieldTypes()); + persist(new TemporalFieldTypes()); + persist(new TemporalFieldTypes()); + em.clear(); + Calendar cal = + em.createQuery("SELECT t.calendarTimeZoneField FROM TemporalFieldTypes t WHERE 1=1", Calendar.class) + .setMaxResults(1).getSingleResult(); + assertFalse(cal instanceof ProxyCalendar); + + List cals = + em.createQuery("SELECT t.calendarTimeZoneField FROM TemporalFieldTypes t WHERE 1=1", Calendar.class) + .setMaxResults(3).getResultList(); + for (Calendar c : cals) { + assertFalse(c instanceof ProxyCalendar); + } + } + } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/LRSEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/LRSEntity.java index 04c1598bf..8a957876a 100755 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/LRSEntity.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/LRSEntity.java @@ -40,7 +40,7 @@ public class LRSEntity { @ManyToMany @OrderBy("name ASC") @LRS - private Collection lrsList = new ArrayList(); + private Collection lrsList; public long getId() { return id; @@ -54,7 +54,10 @@ public class LRSEntity { this.name = name; } - public Collection getLRSList() { - return lrsList; + public Collection getLRSList() { + if (lrsList == null) { + lrsList = new ArrayList(); + } + return lrsList; } }