diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java index 016d53d97..57232a4bc 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java @@ -410,14 +410,13 @@ public class EmbedFieldStrategy //### we selected the embedded object fields and load the object //### immediately; this will be inefficient when the embedded object //### was not selected after all - StoreContext ctx = store.getContext(); OpenJPAStateManager em = ctx.embed(null, null, sm, field); sm.storeObject(field.getIndex(), em.getManagedInstance()); FieldMapping[] fields = field.getEmbeddedMapping().getFieldMappings(); Object eres, processed; - boolean loaded = false; + boolean needsLoad = false; for (int i = 0; i < fields.length; i++) { eres = res.getEager(fields[i]); res.startDataRequest(fields[i]); @@ -429,18 +428,24 @@ public class EmbedFieldStrategy fields[i].loadEagerParallel(em, store, fetch, eres); if (processed != eres) res.putEager(fields[i], processed); - } else + } else { fields[i].load(em, store, fetch, res); - loaded |= em.getLoaded().get(i); + } + needsLoad = needsLoad || (!em.getLoaded().get(i) && + fetch.requiresFetch(fields[i]) + == FetchConfiguration.FETCH_LOAD); } finally { res.endDataRequest(); } } - // after loading everything from result, load the rest of the - // configured fields - if (loaded) - em.load(fetch); + // After loading everything from result, load the rest of the + // configured fields if anything is missing. + if (needsLoad && + fetch.requiresFetch(field.getFieldMetaData()) == + JDBCFetchConfiguration.FETCH_LOAD) { + em.load(fetch); + } } /** diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java index 71ec7305c..a36c1ed2d 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java @@ -157,7 +157,8 @@ public class HandlerFieldStrategy if (sm != null && sm.getIntermediate(field.getIndex()) != null) return -1; - if (sel.isDistinct() && _lob && !field.isPrimaryKey()) + if (_lob && !field.isPrimaryKey() && (sel.isDistinct() || + eagerMode == JDBCFetchConfiguration.EAGER_NONE)) return -1; sel.select(_cols, field.join(sel)); return 1; diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java index fa6891f50..a807f847d 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java @@ -162,15 +162,13 @@ public class DataSourceFactory { decorators.addAll(decs); } - if (jdbcLog.isTraceEnabled() || sqlLog.isTraceEnabled()) { - // logging decorator - LoggingConnectionDecorator lcd = - new LoggingConnectionDecorator(); - Configurations.configureInstance(lcd, conf, opts); - lcd.getLogs().setJDBCLog(jdbcLog); - lcd.getLogs().setSQLLog(sqlLog); - decorators.add(lcd); - } + // logging decorator + LoggingConnectionDecorator lcd = + new LoggingConnectionDecorator(); + Configurations.configureInstance(lcd, conf, opts); + lcd.getLogs().setJDBCLog(jdbcLog); + lcd.getLogs().setSQLLog(sqlLog); + decorators.add(lcd); dds.addDecorators(decorators); return dds; diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java index 358bda129..9b01fc66f 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java @@ -18,6 +18,8 @@ */ package org.apache.openjpa.jdbc.sql; +import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; @@ -51,7 +53,7 @@ public class MySQLDictionary /** * Whether the driver automatically deserializes blobs. */ - public boolean driverDeserializesBlobs = true; + public boolean driverDeserializesBlobs = false; /** * Whether to inline multi-table bulk-delete operations into MySQL's @@ -70,11 +72,9 @@ public class MySQLDictionary supportsDeferredConstraints = false; constraintNameMode = CONS_NAME_MID; supportsMultipleNontransactionalResultSets = false; - supportsSubselect = false; // old versions requiresAliasForSubselect = true; // new versions supportsSelectStartIndex = true; supportsSelectEndIndex = true; - allowsAliasInBulkClause = false; concatenateFunction = "CONCAT({0},{1})"; @@ -112,6 +112,68 @@ public class MySQLDictionary "ZEROFILL" })); } + public void connectedConfiguration(Connection conn) throws SQLException { + super.connectedConfiguration(conn); + + DatabaseMetaData metaData = conn.getMetaData(); + // The product version looks like 4.1.3-nt + String productVersion = metaData.getDatabaseProductVersion(); + // The driver version looks like mysql-connector-java-3.1.11 (...) + String driverVersion = metaData.getDriverVersion(); + + try { + int[] versions = getMajorMinorVersions(productVersion); + int maj = versions[0]; + int min = versions[1]; + if (maj < 4 || (maj == 4 && min < 1)) { + supportsSubselect = false; + allowsAliasInBulkClause = false; + } + + versions = getMajorMinorVersions(driverVersion); + maj = versions[0]; + if (maj < 5) { + driverDeserializesBlobs = true; + } + } catch (IllegalArgumentException e) { + // we don't understand the version format. + // That is ok. We just take the default values. + } + } + + private static int[] getMajorMinorVersions(String versionStr) + throws IllegalArgumentException { + int beginIndex = 0; + int endIndex = 0; + + versionStr = versionStr.trim(); + char[] charArr = versionStr.toCharArray(); + for (int i = 0; i < charArr.length; i++) { + if (Character.isDigit(charArr[i])) { + beginIndex = i; + break; + } + } + + for (int i = beginIndex+1; i < charArr.length; i++) { + if (charArr[i] != '.' && !Character.isDigit(charArr[i])) { + endIndex = i; + break; + } + } + + if (endIndex < beginIndex) + throw new IllegalArgumentException(); + + String[] arr = versionStr.substring(beginIndex, endIndex).split("\\."); + if (arr.length < 2) + throw new IllegalArgumentException(); + + int maj = Integer.parseInt(arr[0]); + int min = Integer.parseInt(arr[1]); + return new int[]{maj, min}; + } + public String[] getCreateTableSQL(Table table) { String[] sql = super.getCreateTableSQL(table); if (!StringUtils.isEmpty(tableType)) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java index 5bf7969bc..467efdbfd 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java @@ -1124,9 +1124,11 @@ public class FieldMetaData //set "isUsedInOrderBy" to the field ClassMetaData elemCls = getElement() .getDeclaredTypeMetaData(); - FieldMetaData fmd = elemCls.getDeclaredField(decs[i]); - if (fmd != null) - fmd.setUsedInOrderBy(true); + if (elemCls != null) { + FieldMetaData fmd = elemCls.getDeclaredField(decs[i]); + if (fmd != null) + fmd.setUsedInOrderBy(true); + } } _orders = orders; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java index 8e9679f4c..12e185627 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java @@ -30,7 +30,7 @@ import java.util.Comparator; public class InheritanceComparator implements Comparator, Serializable { - private Class _base = null; + private Class _base = Object.class; /** * Set the least-derived type possible; defaults to null. @@ -92,8 +92,6 @@ public class InheritanceComparator private int levels(Class to) { if (to.isInterface()) return to.getInterfaces().length; - if (_base == null) - return 0; for (int i = 0; to != null; i++, to = to.getSuperclass()) if (to == _base) return i; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceOrderedMetaDataList.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceOrderedMetaDataList.java new file mode 100644 index 000000000..79376fb71 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceOrderedMetaDataList.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.meta; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.ListIterator; +import java.io.Serializable; + +public class InheritanceOrderedMetaDataList + implements Serializable { + + private MetaDataInheritanceComparator _comp + = new MetaDataInheritanceComparator(); + private LinkedList buffer = new LinkedList(); + + public boolean add(ClassMetaData meta) { + if (meta == null || buffer.contains(meta)) + return false; + for (ListIterator itr = buffer.listIterator(); + itr.hasNext();) { + int ord = _comp.compare(meta, itr.next()); + if (ord > 0) + continue; + if (ord == 0) + return false; + itr.previous(); + itr.add(meta); + return true; + } + buffer.add(meta); + return true; + } + + public boolean remove(ClassMetaData meta) { + return buffer.remove(meta); + } + + public ClassMetaData peek() { + return buffer.peek(); + } + + public int size() { + return buffer.size(); + } + + public Iterator iterator() { + return buffer.iterator(); + } + + public boolean isEmpty() { + return buffer.isEmpty(); + } + + public void clear() { + buffer.clear(); + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java index 1a5aea3b5..1b5845769 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java @@ -31,7 +31,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.lang.StringUtils; @@ -137,10 +136,10 @@ public class MetaDataRepository private final Collection _registered = new HashSet(); // set of metadatas we're in the process of resolving - private final SortedSet _resolving = new TreeSet - (new MetaDataInheritanceComparator()); - private final SortedSet _mapping = new TreeSet - (new MetaDataInheritanceComparator()); + private final InheritanceOrderedMetaDataList _resolving = + new InheritanceOrderedMetaDataList(); + private final InheritanceOrderedMetaDataList _mapping = + new InheritanceOrderedMetaDataList(); private final List _errs = new LinkedList(); // system listeners @@ -574,7 +573,6 @@ public class MetaDataRepository * if we're still in the process of resolving other metadatas. */ private List resolveMeta(ClassMetaData meta) { - setBaseIfNecessary(meta); if (meta.getPCSuperclass() == null) { // set superclass Class sup = meta.getDescribedType().getSuperclass(); @@ -618,27 +616,6 @@ public class MetaDataRepository return processBuffer(meta, _resolving, MODE_META); } - private void setBaseIfNecessary(ClassMetaData meta) { - if (_resolving == null) - return; - - InheritanceComparator comp = - (InheritanceComparator) _resolving.comparator(); - if (meta.getPCSuperclass() == null) { - Class sup = meta.getDescribedType().getSuperclass(); - Class pBase = null; - while (sup != null && sup != Object.class) { - pBase = sup; - sup = sup.getSuperclass(); - } - if (pBase != null && !pBase.equals(comp.getBase())) { - // setBase() can be called because getMetaData() is - // syncronized - comp.setBase(pBase); - } - } - } - /** * Load mapping information for the given metadata. */ @@ -719,7 +696,8 @@ public class MetaDataRepository /** * Process the given metadata and the associated buffer. */ - private List processBuffer(ClassMetaData meta, SortedSet buffer, int mode) { + private List processBuffer(ClassMetaData meta, + InheritanceOrderedMetaDataList buffer, int mode) { // if we're already processing a metadata, just buffer this one; when // the initial metadata finishes processing, we traverse the buffer // and process all the others that were introduced during reentrant @@ -734,7 +712,7 @@ public class MetaDataRepository ClassMetaData buffered; List processed = new ArrayList(5); while (!buffer.isEmpty()) { - buffered = (ClassMetaData) buffer.first(); + buffered = buffer.peek(); try { buffered.resolve(mode); processed.add(buffered); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/meta/TestMetaDataInheritanceComparator.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/meta/TestMetaDataInheritanceComparator.java index 257e66605..c93377fc4 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/meta/TestMetaDataInheritanceComparator.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/meta/TestMetaDataInheritanceComparator.java @@ -25,10 +25,6 @@ import org.apache.openjpa.persistence.JPAFacadeHelper; public class TestMetaDataInheritanceComparator extends PersistenceTestCase { - public void testInheritanceComparatorWithoutBase() { - inheritanceComparatorHelper(false); - } - public void testInheritanceComparatorWithBase() { inheritanceComparatorHelper(true); } @@ -47,10 +43,6 @@ public class TestMetaDataInheritanceComparator extends PersistenceTestCase { assertTrue(comp.compare(AbstractThing.class, C.class) < 0); } - public void testMetaDataInheritanceComparatorWithoutBase() { - metaDataInheritanceComparatorHelper(false); - } - public void testMetaDataInheritanceComparatorWithBase() { metaDataInheritanceComparatorHelper(true); }