diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java index a00b5a31e..56a1c2bec 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java @@ -19,8 +19,8 @@ package org.apache.openjpa.jdbc.kernel; import java.io.Serializable; -import java.sql.ResultSet; import java.sql.Connection; +import java.sql.ResultSet; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -31,6 +31,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.jdbc.conf.JDBCConfiguration; import org.apache.openjpa.jdbc.meta.ClassMapping; +import org.apache.openjpa.jdbc.sql.JoinSyntaxes; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.FetchConfigurationImpl; import org.apache.openjpa.kernel.StoreContext; @@ -121,6 +122,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setEagerFetchMode(int mode) { + if (mode != DEFAULT + && mode != EagerFetchModes.EAGER_NONE + && mode != EagerFetchModes.EAGER_JOIN + && mode != EagerFetchModes.EAGER_PARALLEL) + throw new IllegalArgumentException( + _loc.get("bad-fetch-mode", new Integer(mode)).getMessage()); + if (mode == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) @@ -145,6 +153,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setSubclassFetchMode(int mode) { + if (mode != DEFAULT + && mode != EagerFetchModes.EAGER_NONE + && mode != EagerFetchModes.EAGER_JOIN + && mode != EagerFetchModes.EAGER_PARALLEL) + throw new IllegalArgumentException( + _loc.get("bad-fetch-mode", new Integer(mode)).getMessage()); + if (mode == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) @@ -160,6 +175,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setResultSetType(int type) { + if (type != DEFAULT + && type != ResultSet.TYPE_FORWARD_ONLY + && type != ResultSet.TYPE_SCROLL_INSENSITIVE + && type != ResultSet.TYPE_SCROLL_SENSITIVE) + throw new IllegalArgumentException(_loc.get("bad-resultset-type", + new Integer(type)).getMessage()); + if (type == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) @@ -174,6 +196,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setFetchDirection(int direction) { + if (direction != DEFAULT + && direction != ResultSet.FETCH_FORWARD + && direction != ResultSet.FETCH_REVERSE + && direction != ResultSet.FETCH_UNKNOWN) + throw new IllegalArgumentException(_loc.get("bad-fetch-direction", + new Integer(direction)).getMessage()); + if (direction == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) @@ -188,6 +217,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setLRSSize(int size) { + if (size != DEFAULT + && size != LRSSizes.SIZE_QUERY + && size != LRSSizes.SIZE_LAST + && size != LRSSizes.SIZE_UNKNOWN) + throw new IllegalArgumentException( + _loc.get("bad-lrs-size", new Integer(size)).getMessage()); + if (size == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) @@ -202,6 +238,13 @@ public class JDBCFetchConfigurationImpl } public JDBCFetchConfiguration setJoinSyntax(int syntax) { + if (syntax != DEFAULT + && syntax != JoinSyntaxes.SYNTAX_SQL92 + && syntax != JoinSyntaxes.SYNTAX_TRADITIONAL + && syntax != JoinSyntaxes.SYNTAX_DATABASE) + throw new IllegalArgumentException( + _loc.get("bad-join-syntax", new Integer(syntax)).getMessage()); + if (syntax == DEFAULT) { JDBCConfiguration conf = getJDBCConfiguration(); if (conf != null) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java index a981484bc..f502478dc 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java @@ -38,6 +38,7 @@ import org.apache.openjpa.jdbc.schema.Schema; import org.apache.openjpa.jdbc.schema.Sequence; import org.apache.openjpa.jdbc.schema.Table; import org.apache.openjpa.kernel.Filters; +import org.apache.openjpa.kernel.MixedLockLevels; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.OpenJPAException; @@ -349,6 +350,9 @@ public class DB2Dictionary else isolationLevel = conf.getTransactionIsolationConstant(); + if (fetch.getReadLockLevel() >= MixedLockLevels.LOCK_PESSIMISTIC_WRITE) + isolationLevel = Connection.TRANSACTION_SERIALIZABLE; + if (isForUpdate) { switch (db2ServerType) { case db2ISeriesV5R3OrEarlier: diff --git a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties index ad6fb799f..4f22367cc 100644 --- a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties +++ b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties @@ -1,145 +1,154 @@ -# 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. - -error-rollback: An error occurred attempting to rollback to the savepoint "{0}" -error-save: An error occurred attempting to set the savepoint "{0}". This \ - driver may not support JDBC 3 savepoints. -mult-mapping-aggregate: Cannot perform an aggregate query on a hierarchy with \ - unjoined subclasses: {0} -sqlquery-missing-params: SQL query "{0}" declares a parameter index "{1}" for \ - which no value was given. The given parameters were: {2} -sqlquery-fewer-params: SQL query "{0}" declares {1} distinct parameter(s), \ - but only {2} parameters are given. Given parameter values are "{3}". -no-sql: You have not specified a SQL filter to execute in your SQL query. -del-ins-cycle: An unresolvable constraint cycle was detected. This typically \ - means that you are persisting a new object with the same primary key value \ - as an object you are deleting in the same transaction, and at the same \ - time you have circular foreign key dependencies in the transaction. The \ - combination of these two factors can sometimes lead to a situation in \ - which OpenJPA cannot meet all the database constraints. -ref-cycle: An unresolvable constraint cycle was detected. This typically \ - means that a mapping in a table other than the class'' primary table has \ - a foreign key that is part of a circular foreign key dependency. OpenJPA \ - sometimes cannot meet circular dependencies when some of the involved \ - mappings are in secondary tables. -update-failed-no-failed-obj: Database operation failed. Update count for SQL \ - statement was {0}. Statement: {1} -virtual-mapping: Cannot instantiate virtual mapping "{0}". -press-key-end: Server running. Press enter to stop. -no-server-conf: There is no persistence server configured. -server-usage: Usage: \ - java org.apache.openjpa.jdbc.kernel.StartPersistenceServer\n\ - \t[-properties/-p ]\n\ - \t[- ]* -cant-lock-on-load: The database is unable to lock this query. Each object \ - matching the query will be locked individually after it is loaded; \ - however, it is technically possible that another transaction could modify \ - the data before the lock is obtained. See the documentation on Object \ - Locking for details.\n"{0}" -start-trans-for-lock: Though you are using optimistic transactions, OpenJPA is \ - now beginning a datastore transaction because you have requested a lock \ - on some data. -millis-query-timeout: JDBC locking does not support millisecond-granularity \ - timeouts. Use timeouts that are multiples of 1000 for even second values. -batch-not-supported: The update count for the statement was an invalid \ - value ({0}). This indicates that your database or JDBC driver does not \ - have complete support for executing batch statements. Batch \ - functionality should be disabled by including "BatchLimit=0" in \ - your openjpa.jdbc.DBDictionary configuration property. Statement: {1} -bad-synch-mappings: Invalid SynchronizeMappings operation ("{0}") specified. \ - Valid operations are: {1} -make-native-seq: Creating sequence. -drop-native-seq: Dropping sequence. -make-seq-table: Creating sequence table. -drop-seq-table: Dropping sequence table. -bad-seq-up: Attempt to update the sequence table "{0}" failed. The sequence \ - table is typically created when you run the mappingtool''s refresh action \ - on any datastore identity class. If you have not run the mappingtool but \ - want to create the sequence table, run:\n\ - java org.apache.openjpa.jdbc.kernel.TableJDBCSeq -action add -bad-seq-type: This sequence of type "{0}" cannot generate values for \ - persistent type "{1}". -no-seq-sql: Error instantiating named sequence "{0}": Your database dictionary \ - does not support native sequences. To tell the dictionary how to select \ - sequence values, use:\n\ - openjpa.jdbc.DBDictionary: NextSequenceQuery="SELECT NEXT VALUE \ - FOR '{0}"\n\ - Where the above string is replaced with the proper SQL for your database. -invalid-seq-sql: No rows returned for sql "{0}". Check your configuration. -insert-seq: Inserting row for this mapping into sequence table. -no-seq-row: There is no row for mapping "{0}" in sequence table "{1}", and \ - the attempt to insert a row has apparently failed. -update-seq: Updating sequence values. -null-join: Attempt to add a null/empty fetch join field. -get-seq: Getting current sequence values. -seq-usage: Usage: java org.apache.openjpa.jdbc.kernel.TableJDBCSeq\n\ - \t[-properties/-p ]\n\ - \t[- ]*\n\ - \t-action/-a [value] -clstable-seq-usage: Usage: \ - java org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq\n\ - \t[-properties/-p ]\n\ - \t[- ]*\n\ - \t-action/-a \n\ - \t[class name | .java file | .class file | .jdo file] [value] -native-seq-usage: Usage: java org.apache.openjpa.jdbc.kernel.NativeJDBCSeq\n\ - \t[-properties/-p ]\n\ - \t[- ]* -bad-level: Invalid isolation level. Valid levels are -1, \ - Connection.TRANSACTION_NONE, Connection.TRANSACTION_READ_UNCOMMITTED, \ - Connection.TRANSACTION_READ_COMMITTED, \ - Connection.TRANSACTION_REPEATABLE_READ, or \ - Connection.TRANSACTION_SERIALIZABLE. Specified value: {0}. -no-nullable-fk: No nullable foreign key found to resolve circular flush\n\ - dependency. During flush processing, changes to instances, new\n\ - instances, and deleted instances must be processed in a specific sequence\n\ - to avoid foreign key constraint violations. The changes required in this\n\ - transaction cannot be reordered because none of the foreign key constraints\n\ - is nullable (optional). -graph-not-cycle-free: A circular flush dependency has been found after all \ - circular dependencies should have been resolved. -batch_limit: The batch limit is set to {0}. -batch_update_info: ExecuteBatch command returns update count {0} for \ - statement {1}. -prepared-query-cached: Query "{0}" is cached as target query "{1}" -prepared-query-not-cachable: Query "{0}" is not fit for caching. -prepared-query-invalidate: Query "{0}" is invalidated and removed from cache. -prepared-query-uncache-strong: Query "{0}" is permanently excluded from cache. -prepared-query-uncache-weak: Query "{0}" is excluded temporarily due to "{1}". -prepared-query-add-pattern: Adding a Query exclusion pattern "{0}" has caused \ - following {1} cached queries to be removed from the cache: "{2}". -prepared-query-remove-pattern: Removing a Query exclusion pattern "{0}" caused \ - following {1} queries to be re-inserted in the cache: "{2}". -uparam-mismatch: Supplied user parameters "{1}" do not match expected \ - parameters "{0}" for the prepared query "{2}". -uparam-null: No user parameter was given. Expected parameters "{0}" for the \ - prepared query "{1}". -uparam-coll-size: Parameter "{0}" has a value "{1}" which is not compatible \ - with the available positions {2} in the parameter list of the prepared query -uparam-no-pos: User parameter "{0}" does not appear in any position in the \ - prepared query "{1}". -uparam-pc-key: Class "{0}" uses {1} primary key columns but corresponding \ - positions {2} in the parameter list of the prepared query is not compatible. -uparam-missing: Parameter {0} in SQL Query "{1}" is not given a value. The \ - parameters given is "{2}". -finder-cached: Cached finder for "{0}" SQL: "{1}" -finder-not-cachable: Finder for "{0}" is not cachable. -finder-add-pattern: Exclusion pattern "{0}" for finder query has invalidated \ - {1} existing entries "{2}" -optimistic-violation-lock: An optimistic lock violation was detected when \ - locking object instance. -sql-warning: The statement resulted in SQL warning: {0} +# 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. + +error-rollback: An error occurred attempting to rollback to the savepoint "{0}" +error-save: An error occurred attempting to set the savepoint "{0}". This \ + driver may not support JDBC 3 savepoints. +mult-mapping-aggregate: Cannot perform an aggregate query on a hierarchy with \ + unjoined subclasses: {0} +sqlquery-missing-params: SQL query "{0}" declares a parameter index "{1}" for \ + which no value was given. The given parameters were: {2} +sqlquery-fewer-params: SQL query "{0}" declares {1} distinct parameter(s), \ + but only {2} parameters are given. Given parameter values are "{3}". +no-sql: You have not specified a SQL filter to execute in your SQL query. +del-ins-cycle: An unresolvable constraint cycle was detected. This typically \ + means that you are persisting a new object with the same primary key value \ + as an object you are deleting in the same transaction, and at the same \ + time you have circular foreign key dependencies in the transaction. The \ + combination of these two factors can sometimes lead to a situation in \ + which OpenJPA cannot meet all the database constraints. +ref-cycle: An unresolvable constraint cycle was detected. This typically \ + means that a mapping in a table other than the class'' primary table has \ + a foreign key that is part of a circular foreign key dependency. OpenJPA \ + sometimes cannot meet circular dependencies when some of the involved \ + mappings are in secondary tables. +update-failed-no-failed-obj: Database operation failed. Update count for SQL \ + statement was {0}. Statement: {1} +virtual-mapping: Cannot instantiate virtual mapping "{0}". +press-key-end: Server running. Press enter to stop. +no-server-conf: There is no persistence server configured. +server-usage: Usage: \ + java org.apache.openjpa.jdbc.kernel.StartPersistenceServer\n\ + \t[-properties/-p ]\n\ + \t[- ]* +cant-lock-on-load: The database is unable to lock this query. Each object \ + matching the query will be locked individually after it is loaded; \ + however, it is technically possible that another transaction could modify \ + the data before the lock is obtained. See the documentation on Object \ + Locking for details.\n"{0}" +start-trans-for-lock: Though you are using optimistic transactions, OpenJPA is \ + now beginning a datastore transaction because you have requested a lock \ + on some data. +millis-query-timeout: JDBC locking does not support millisecond-granularity \ + timeouts. Use timeouts that are multiples of 1000 for even second values. +batch-not-supported: The update count for the statement was an invalid \ + value ({0}). This indicates that your database or JDBC driver does not \ + have complete support for executing batch statements. Batch \ + functionality should be disabled by including "BatchLimit=0" in \ + your openjpa.jdbc.DBDictionary configuration property. Statement: {1} +bad-synch-mappings: Invalid SynchronizeMappings operation ("{0}") specified. \ + Valid operations are: {1} +make-native-seq: Creating sequence. +drop-native-seq: Dropping sequence. +make-seq-table: Creating sequence table. +drop-seq-table: Dropping sequence table. +bad-seq-up: Attempt to update the sequence table "{0}" failed. The sequence \ + table is typically created when you run the mappingtool''s refresh action \ + on any datastore identity class. If you have not run the mappingtool but \ + want to create the sequence table, run:\n\ + java org.apache.openjpa.jdbc.kernel.TableJDBCSeq -action add +bad-seq-type: This sequence of type "{0}" cannot generate values for \ + persistent type "{1}". +no-seq-sql: Error instantiating named sequence "{0}": Your database dictionary \ + does not support native sequences. To tell the dictionary how to select \ + sequence values, use:\n\ + openjpa.jdbc.DBDictionary: NextSequenceQuery="SELECT NEXT VALUE \ + FOR '{0}"\n\ + Where the above string is replaced with the proper SQL for your database. +invalid-seq-sql: No rows returned for sql "{0}". Check your configuration. +insert-seq: Inserting row for this mapping into sequence table. +no-seq-row: There is no row for mapping "{0}" in sequence table "{1}", and \ + the attempt to insert a row has apparently failed. +update-seq: Updating sequence values. +null-join: Attempt to add a null/empty fetch join field. +get-seq: Getting current sequence values. +seq-usage: Usage: java org.apache.openjpa.jdbc.kernel.TableJDBCSeq\n\ + \t[-properties/-p ]\n\ + \t[- ]*\n\ + \t-action/-a [value] +clstable-seq-usage: Usage: \ + java org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq\n\ + \t[-properties/-p ]\n\ + \t[- ]*\n\ + \t-action/-a \n\ + \t[class name | .java file | .class file | .jdo file] [value] +native-seq-usage: Usage: java org.apache.openjpa.jdbc.kernel.NativeJDBCSeq\n\ + \t[-properties/-p ]\n\ + \t[- ]* +bad-level: Invalid isolation level. Valid levels are -1, \ + "none"(0), "read-uncommitted"(1), "read-committed"(2), \ + "repeatable-read"(4) or "serializable"(8). Specified value: {0}. +no-nullable-fk: No nullable foreign key found to resolve circular flush\n\ + dependency. During flush processing, changes to instances, new\n\ + instances, and deleted instances must be processed in a specific sequence\n\ + to avoid foreign key constraint violations. The changes required in this\n\ + transaction cannot be reordered because none of the foreign key constraints\n\ + is nullable (optional). +graph-not-cycle-free: A circular flush dependency has been found after all \ + circular dependencies should have been resolved. +batch_limit: The batch limit is set to {0}. +batch_update_info: ExecuteBatch command returns update count {0} for \ + statement {1}. +prepared-query-cached: Query "{0}" is cached as target query "{1}" +prepared-query-not-cachable: Query "{0}" is not fit for caching. +prepared-query-invalidate: Query "{0}" is invalidated and removed from cache. +prepared-query-uncache-strong: Query "{0}" is permanently excluded from cache. +prepared-query-uncache-weak: Query "{0}" is excluded temporarily due to "{1}". +prepared-query-add-pattern: Adding a Query exclusion pattern "{0}" has caused \ + following {1} cached queries to be removed from the cache: "{2}". +prepared-query-remove-pattern: Removing a Query exclusion pattern "{0}" caused \ + following {1} queries to be re-inserted in the cache: "{2}". +uparam-mismatch: Supplied user parameters "{1}" do not match expected \ + parameters "{0}" for the prepared query "{2}". +uparam-null: No user parameter was given. Expected parameters "{0}" for the \ + prepared query "{1}". +uparam-coll-size: Parameter "{0}" has a value "{1}" which is not compatible \ + with the available positions {2} in the parameter list of the prepared query +uparam-no-pos: User parameter "{0}" does not appear in any position in the \ + prepared query "{1}". +uparam-pc-key: Class "{0}" uses {1} primary key columns but corresponding \ + positions {2} in the parameter list of the prepared query is not compatible. +uparam-missing: Parameter {0} in SQL Query "{1}" is not given a value. The \ + parameters given is "{2}". +finder-cached: Cached finder for "{0}" SQL: "{1}" +finder-not-cachable: Finder for "{0}" is not cachable. +finder-add-pattern: Exclusion pattern "{0}" for finder query has invalidated \ + {1} existing entries "{2}" +optimistic-violation-lock: An optimistic lock violation was detected when \ + locking object instance. +sql-warning: The statement resulted in SQL warning: {0} +bad-fetch-mode: Invalid fetch mode. Valid values are \ + "none"(0), "join"(1) or "parallel"(2). Specified value: {0}. +bad-resultset-type: Invalid result set type. Valid values are \ + "forward-only"(1003), "scroll-insensitive"(1004) or \ + "scroll-sensitive"(1005). Specified value: {0}. +bad-fetch-direction: Invalid fetch direction. Valid values are \ + "forward"(1000), "reverse"(1001) or "unknown"(1002). Specified value: {0}. +bad-lrs-size: Invalid LRS size. Valid values are \ + "unknown"(0), "last"(1) or "query"(2). Specified value: {0}. +bad-join-syntax: Invalid join syntax. Valid values are \ + "sql92"(0), "tradition"(1) or "database"(2). Specified value: {0}. diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractHintHandler.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractHintHandler.java new file mode 100644 index 000000000..e90bb4d4c --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractHintHandler.java @@ -0,0 +1,124 @@ +/* + * 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.kernel; + +import java.io.Serializable; +import java.lang.reflect.Method; + +import org.apache.openjpa.conf.OpenJPAConfiguration; +import org.apache.openjpa.enhance.Reflection; +import org.apache.openjpa.lib.util.Localizer; + +/** + * Default hint handler abstract base class. + * + * @since 2.0.0 + * @nojavadoc + */ +public abstract class AbstractHintHandler implements Serializable { + + private static final Localizer _loc = Localizer + .forPackage(AbstractHintHandler.class); + + protected static final String DOT = "."; + protected static final String BLANK = ""; + + protected static final String PREFIX_OPENJPA = "openjpa."; + protected static final String PREFIX_JDBC = PREFIX_OPENJPA + "jdbc."; + + protected FetchConfigurationImpl _fConfig; + + /** + * Constructor; supply delegate. + */ + public AbstractHintHandler(FetchConfigurationImpl fConfig) { + _fConfig = fConfig; + } + + protected abstract boolean setHintInternal(String hintName, Object value, + boolean validateThrowException); + + public boolean setHint(String hintName, Object value, + boolean validateThrowException) { + String key = hintToKey(hintName); + boolean valueSet = !hintName.equals(key); + if (hasPrecedent(hintName)) { + try { + valueSet |= setHintInternal(key, value, validateThrowException); + } catch (RuntimeException rte) { + if (validateThrowException) { + if (rte instanceof IllegalArgumentException) + throw rte; + else if (rte instanceof ClassCastException) + throw new IllegalArgumentException(_loc.get( + "bad-hint-value", key, value, rte.getMessage()) + .getMessage()); + else + handleException(rte); + } else + _fConfig.getContext().getConfiguration().getLog( + OpenJPAConfiguration.LOG_RUNTIME) + .warn( + _loc.get("bad-hint-value", key, value, rte + .getMessage())); + } + } else + valueSet = true; + return valueSet; + } + + protected String hintToKey(String key) { + return key; + } + + protected boolean hasPrecedent(String key) { + return true; + } + + protected void handleException(RuntimeException e) { + throw e; + } + + protected final boolean hintToSetter(Object target, String k, + Object value) { + if (target == null || k == null) + return false; + // remove key prefix as the source of property name + k = getSuffixOf(k); + Method setter = Reflection.findSetter(target.getClass(), k, true); + Class paramType = setter.getParameterTypes()[0]; + if (Enum.class.isAssignableFrom(paramType) && value instanceof String) { + // to accomodate alias name input in relationship with enum values + String strValue = ((String) value).toUpperCase().replace('-', '_'); + value = Enum.valueOf(paramType, strValue); + } + Filters.hintToSetter(target, k, value); + return true; + } + + protected static String getPrefixOf(String key) { + int firstDot = key == null ? -1 : key.indexOf(DOT); + return (firstDot != -1) ? key.substring(0, firstDot) : key; + } + + protected static String getSuffixOf(String key) { + int lastDot = key == null ? -1 : key.lastIndexOf(DOT); + return (lastDot != -1) ? key.substring(lastDot + 1) : key; + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java index 819feab2f..f047c4251 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java @@ -475,6 +475,14 @@ public class DelegatingFetchConfiguration } } + public void addHint(String name, Object value) { + try { + _fetch.addHint(name, value); + } catch (RuntimeException re) { + throw translate(re); + } + } + public Map getHints() { try { return _fetch.getHints(); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java index 256fa7ba7..a540f0d1e 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java @@ -337,6 +337,15 @@ public interface FetchConfiguration */ public Object getHint (String name); + /** + * Adds the hint and the associated value to the list. + * + * @param name the name of the hint + * @param value the value of the hint + * @since 2.0.0 + */ + public void addHint(String name, Object value); + /** * Returns an immutable view of the currently active hints and their values. * diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationHintHandler.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationHintHandler.java new file mode 100644 index 000000000..42aadb690 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationHintHandler.java @@ -0,0 +1,68 @@ +/* + * 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.kernel; + +import java.util.HashMap; +import java.util.Map; + +/** + * Fetch configuration hint handler. Handles openjpa.* and openjpa.jdbc.* hints. + * + * @since 2.0.0 + * @nojavadoc + */ +public class FetchConfigurationHintHandler extends AbstractHintHandler { + + protected static final Map hintsMap = + new HashMap(); + + static { + // Initialize hint to property name mapping. + hintsMap.put(PREFIX_JDBC + "TransactionIsolation", "Isolation"); + } + + /** + * Constructor; supply delegate. + */ + public FetchConfigurationHintHandler(FetchConfigurationImpl fConfig) { + super(fConfig); + } + + public boolean setHintInternal(String hintName, Object value, + boolean validateThrowException) { + boolean valueSet = false; + String longPrefix = hintName + .substring(0, hintName.lastIndexOf(DOT) + 1); + if ((longPrefix.equals(PREFIX_JDBC) || longPrefix + .equals(PREFIX_OPENJPA))) { + valueSet = hintToSetter(_fConfig, hintToPropName(hintName), value); + } else { + valueSet = true; + } + return valueSet; + } + + private String hintToPropName(String hintName) { + String propName = hintsMap.get(hintName); + if (propName == null) { + propName = hintName; + } + return propName; + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java index be0fc5315..ab1a70a42 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java @@ -98,6 +98,7 @@ public class FetchConfigurationImpl private boolean _load = true; private int _availableRecursion; private int _availableDepth; + private FetchConfigurationHintHandler _hintHandler; public FetchConfigurationImpl() { this(null); @@ -106,6 +107,7 @@ public class FetchConfigurationImpl protected FetchConfigurationImpl(ConfigurationState state) { _state = (state == null) ? new ConfigurationState() : state; _availableDepth = _state.maxFetchDepth; + _hintHandler = new FetchConfigurationHintHandler(this); } public StoreContext getContext() { @@ -239,6 +241,13 @@ public class FetchConfigurationImpl } public FetchConfiguration setFlushBeforeQueries(int flush) { + if (flush != DEFAULT + && flush != QueryFlushModes.FLUSH_TRUE + && flush != QueryFlushModes.FLUSH_FALSE + && flush != QueryFlushModes.FLUSH_WITH_CONNECTION) + throw new IllegalArgumentException(_loc.get( + "bad-flush-before-queries", new Integer(flush)).getMessage()); + if (flush == DEFAULT && _state.ctx != null) _state.flushQuery = _state.ctx.getConfiguration(). getFlushBeforeQueriesConstant(); @@ -455,13 +464,15 @@ public class FetchConfigurationImpl public int getReadLockLevel() { - String hintKey = "openjpa.FetchPlan.ReadLockLevel"; - if (getHint(hintKey) != null) { + String lockModeKey = "openjpa.FetchPlan.ReadLockMode"; + String deferLockModeKey = lockModeKey + ".Defer"; + Integer value = (Integer)getHint(deferLockModeKey); + if (value != null) { if (isActiveTransaction()) { - setReadLockLevel((Integer)removeHint(hintKey)); - } else { - return (Integer)getHint(hintKey); - } + removeHint(deferLockModeKey); + setReadLockLevel(value); + } else + return value; } return _state.readLockLevel; } @@ -470,6 +481,16 @@ public class FetchConfigurationImpl if (_state.ctx == null) return this; + if (level != DEFAULT + && level != MixedLockLevels.LOCK_NONE + && level != MixedLockLevels.LOCK_OPTIMISTIC + && level != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT + && level != MixedLockLevels.LOCK_PESSIMISTIC_READ + && level != MixedLockLevels.LOCK_PESSIMISTIC_WRITE + && level != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) + throw new IllegalArgumentException(_loc.get( + "bad-lock-level", new Integer(level)).getMessage()); + lock(); try { assertActiveTransaction(); @@ -485,13 +506,15 @@ public class FetchConfigurationImpl } public int getWriteLockLevel() { - String hintKey = "openjpa.FetchPlan.WriteLockLevel"; - if (getHint(hintKey) != null) { + String lockModeKey = "openjpa.FetchPlan.WriteLockMode"; + String deferLockModeKey = lockModeKey + ".Defer"; + Integer value = (Integer)getHint(deferLockModeKey); + if (value != null) { if (isActiveTransaction()) { - setReadLockLevel((Integer)removeHint(hintKey)); - } else { - return (Integer)getHint(hintKey); - } + removeHint(deferLockModeKey); + setWriteLockLevel(value); + } else + return value; } return _state.writeLockLevel; } @@ -500,6 +523,16 @@ public class FetchConfigurationImpl if (_state.ctx == null) return this; + if (level != DEFAULT + && level != MixedLockLevels.LOCK_NONE + && level != MixedLockLevels.LOCK_OPTIMISTIC + && level != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT + && level != MixedLockLevels.LOCK_PESSIMISTIC_READ + && level != MixedLockLevels.LOCK_PESSIMISTIC_WRITE + && level != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) + throw new IllegalArgumentException(_loc.get( + "bad-lock-level", new Integer(level)).getMessage()); + lock(); try { assertActiveTransaction(); @@ -537,6 +570,16 @@ public class FetchConfigurationImpl } public void setHint(String name, Object value) { + setHint(name, value, false); + } + + public void setHint(String name, Object value, + boolean validThrowException) { + if(_hintHandler.setHint(name, value, validThrowException)) + addHint(name, value); + } + + public void addHint(String name, Object value) { lock(); try { if (_state.hints == null) @@ -550,7 +593,7 @@ public class FetchConfigurationImpl public Object getHint(String name) { return (_state.hints == null) ? null : _state.hints.get(name); } - + public Object removeHint(String name) { return (_state.hints == null) ? null : _state.hints.remove(name); } diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index 3b1303ae7..c7606e460 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -1,411 +1,419 @@ -# 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. - -cant-convert-result: There is no conversion between query projection type \ - "{0}" and result type "{1}". -unloaded-detached: Attempt to access an unloaded field of detached instance \ - "{0}". -meta-unknownid: Cannot manipulate identity of type "{0}": it''s identity type \ - is unknown. -new-abstract: Cannot create an instance of "{0}": abstract classes are not \ - yet supported. -bad-new-query: Attempt to construct a query from an extent or class. You must \ - pass a (possibly null) query string or template to the query factory \ - method when creating the query. -update-restrict: Detected attempt to modify field "{0}" with value strategy \ - "restrict". -reentrant-flush: Detected reentrant flush. Make sure your flush-time instance \ - callback methods or event listeners do not invoke any operations that \ - require the in-progress flush to complete. -rolled-back: The transaction has been rolled back. See the nested exceptions \ - for details on the errors that occurred. -bad-lock-level: This lock manager does not recognize lock level "{0}". -pessimistic-mutate: You are attempting to directly mutate a persistent second \ - class object (such as a collection or map field) that you obtained before \ - the transaction began. After beginning a datastore transaction, you \ - must re-obtain any references to mutable second class objects from the \ - owning persistent object. Detected attempt to mutate value of field "{0}" \ - in instance "{1}". This instance may not be locked correctly. -not-derefed: Encountered unknown dependent instance "{0}". This error is \ - often caused by either removing a dependent instance from one dependent \ - field, but not other dependent fields that reference it, or by removing a \ - dependent instance from its owning field, flushing \ - (causing the unreferenced dependent instance to be deleted), and then \ - trying to assign the deleted instance to another field before commit. \ - The instance cannot be un-deleted, resulting in an error. Make sure not \ - to leave dangling dependent references to objects, and to reassign \ - dependent objects before flush so that OpenJPA does not think they are \ - unreferenced and therefore safe to delete. -init-null-pc: Attempt to initialize a state manager with a null \ - persistence-capable instance for type "{0}". This is often caused by \ - attempting to load an instance of an abstract class, or \ - neglecting to use a class indicator when the base persistence-capable \ - class in an inheritance tree is abstract. -init-sm-pc: Attempt to initialize a state manager with an instance that is \ - already managed ("{0}"). You might be trying to persist this instance \ - in two threads at the same time. -bad-ds-oid: The type "{0}" declares datastore identity but the value \ - passed to lookup of type "{1}" is not a OpenJPA id instance. -null-oids: Some of the object ids passed to getObjectsById were null. -marked-rollback: The transaction cannot be committed, because it was already \ - marked for rollback only. The transaction will be rolled back instead. \ - The cause of the rollback-only status is reported in the embedded stack. -refresh-flushed: You cannot refresh an instance that has been flushed to the \ - data store. -pc-loader-different: Attempt to cast instance "{0}" to PersistenceCapable failed. \ - The object implemented org.apache.openjpa.enhance.PersistenceCapable, \ - but the instance of that interface was loaded by two different ClassLoaders: \ - "{1}" and "{2}". -pc-cast: Attempt to cast instance "{0}" to PersistenceCapable failed. Ensure \ - that it has been enhanced. -del-instance: The instance of type "{0}" with oid "{1}" no longer exists in \ - the data store. This may mean that you deleted the instance in a separate \ - transaction, but this context still has a cached version. -no-broker-class: The specified type "{0}" could not be loaded. Please ensure \ - that the class exists in the project class path. -bad-embed: Attempt to set an embedded value for unembeddable field "{0}". \ - Please report this error to OpenJPA support. -embed-ref: You are attempting to access an embedded object reference \ - that was obtained before the last transaction status change. After \ - transactions begin and end, all references to embedded objects become \ - invalid; you have to re-acquire the reference from the owning persistent \ - object. -deleted: Operation attempted on a deleted instance. -dirty: Illegal operation attempted on a dirty instance: dirty objects cannot \ - be evicted or made transient or non-transactional. -nested-exceps: This operation failed for some instances. See the nested \ - exceptions array for details. -new: Illegal operation attempted on a newly persisted instance: new objects \ - cannot be evicted or made transient or non-transactional. -transient: Illegal operation attempted on a transient instance. -not-active: Can only perform operation while a transaction is active. -trans-active: The "{0}" transaction property cannot be set during an \ - active transaction. -active: This operation cannot be performed while a Transaction is active. -closed: The context has been closed. The stack trace at which the \ - context was closed is held in the embedded exception. -closed-notrace: The context has been closed. The stack trace at which the \ - context was closed is available if Runtime=TRACE logging is enabled. -closed-factory: The factory has been closed. The stack trace at \ - which the factory was closed is held in the embedded exception. -closed-factory-notrace: The factory has been closed. The stack trace at \ - which the factory was closed is available if Runtime=TRACE logging is \ - enabled. -non-trans-read: To perform reads on persistent data outside of a transaction, \ - the "NontransactionalRead" property must be set on the Transaction. -non-trans-write: To perform writes on persistent data outside of a \ - transaction, the "NontransactionalWrite" property must be set to true. -write-operation: To perform this operation, it must be written within a transaction, \ - or your settings must allow nontransactional writes and must not detach \ - all nontransactional reads. -not-managed: The given instance "{0}" is not managed by this context. -trans-not-managed: This broker is not configured to use managed transactions. -bad-detached-op: You cannot perform operation {0} on detached object "{1}". \ - This operation only applies to managed objects. -persist-detached: Attempt to persist detached object "{0}". If this is a new \ - instance, make sure any version and/or auto-generated primary key fields are \ - null/default when persisting. -null-value: The field "{0}" of instance "{1}" contained a null value; \ - the metadata for this field specifies that nulls are illegal. -change-identity: Attempt to change a primary key field of an instance that \ - already has a final object id. Only new, unflushed instances whose id you \ - have not retrieved can have their primary keys changed. -managed-oid: You cannot assign managed object "{0}" to the primary key field \ - of "{1}". Embedded primary key values must be transient objects. -changed-oid: You have modified the object id field of "{2}". Its old value \ - was "{0}", and its new value is "{1}". Object id fields are immutable \ - once the object id of the instance has been assigned. -cache-exists: An object of type "{0}" with oid "{1}" already exists in this \ - context; another cannot be persisted. -null-trans: Attempt to commit a null javax.transaction.Transaction. Some \ - application servers set the transaction to null if a rollback occurs. -end-trans-error: An exception occurred while ending the transaction. This \ - exception will be re-thrown. -not-bound: The file named "{0}" could not be found. -naming-exception: A NamingException was thrown while obtaining the \ - factory at "{0}" from JNDI. -attach-deleted: The object "{0}" with id "{1}" has been deleted and \ - cannot be attached. -not-detachable: The class "{0}" does not declare the "detachable" metadata \ - extension, so cannot be detached. -not-copyable: Attempt to copy field "{0}" failed. The field is \ - not copyable. This can occur with custom SCO types. Only standard or \ - immutable SCO types can be attached and detached. -no-detach-object-id: Cannot access the detached object id of class "{0}". \ - Ensure that the class has the "detachable" metadata extension, and \ - the the class has been re-enhanced. -attach-version-del: Attempted to attach deleted instance type "{0}" with oid \ - "{1}". If the instance is new, the version field should be left to its \ - default value. -attach-wrongclass: Attempted to attach instance "{0}" of type "{1}", but this \ - instance is already in the datastore as type "{2}". -sjvm-acquired-lock: Acquired an exclusive lock "{0}" on oid "{1}". -sjvm-released-lock: Released lock "{0}". -conn-not-supported: This data store cannot return connections. -incremental-flush-not-supported: This data store does not support incremental \ - flushing. If you got this error while performing a query, make sure that \ - you have not set the FlushBeforeQueries option to true, either by \ - setting that option in your configuration file, or by programmatically \ - setting the current FetchConfiguration''s FlushBeforeQueries property \ - to QueryFlushModes.FLUSH_TRUE. -nontrans-read-not-supported: This data store does not support nontransactional \ - reads. Set the NontransactionalRead property to false. -optimistic-not-supported: This datastore does not support optimistic \ - transactions. Set the Optimistic property to false. -restore-unset: The RestoreValues option is off, so initial values are \ - not available. Turn on RestoreValues to be able to obtain initial \ - values. -mutable-restore-unset: The RestoreValues option is not set to "all", \ - initial values of mutable fields are not available. Set RestoreValues to \ - "all" in your properties to be able to obtain initial mutable values. -initial-unloaded: OpenJPA cannot provide the initial value for field "{0}" \ - because the field was never loaded before being changed. -dup-oid-assign: Attempt to assign id "{0}" to new instance "{1}" failed; \ - there is already an object in the L1 cache with this id. \ - You must delete this object (in a previous transaction or the current one) \ - before reusing its id. This error can also occur when a horizontally \ - or vertically mapped classes uses auto-increment application identity and \ - does not use a hierarchy of application identity classes. -dup-load: Cannot load object with id "{0}". Instance "{1}" with the same id \ - already exists in the L1 cache. This can occur when you \ - assign an existing id to a new instance, and before flushing attempt to \ - load the existing instance for that id. -bad-id-value: The given value "{0}" cannot be converted into an identity \ - for "{2}". The value is the wrong type ({1}). -factory-init: Starting OpenJPA {0} -factory-properties: Properties: {0} -inverse-consistency: An inverse inconsistency in the object model was \ - detected while flushing the field "{0}" of the instance with id "{1}" \ - in context "{2}". -no-brokerfactory: You did not name the factory class with the required \ - property openjpa.BrokerFactory. Normally this property defaults \ - appropriately; have you forgotten to include all the OpenJPA jars in your \ - classpath? -brokerfactory-excep: There was an error when invoking the static \ - getInstance method on the named factory class "{0}". See the \ - nested exception for details. -new-brokerfactory-excep: There was an error when invoking the static \ - newInstance method on the named factory class "{0}". See the \ - nested exception for details. -bad-brokerfactory: Could not invoke the static getInstance method on the \ - named factory class "{0}". -bad-new-brokerfactory: Could not invoke the static newInstance method on the \ - named factory class "{0}". -bad-brokerfactory-class: The named BrokerFactory "{0}" is not valid. -instantiate-abstract: Cannot instantiate abstract class of type "{0}" with \ - object id "{1}"; this may indicate that the inheritance discriminator \ - for the class is not configured correctly. -nontrans-proxied: You cannot make a property access object created with "new" \ - nontransactional. -no-field: Field "{0}" is not declared in "{1}", or is not managed. -no-field-index: "{0}" is not the index of any managed field in "{1}". -cant-cascade-persist: Encountered unmanaged object in persistent field \ - "{0}" during flush. However, this field does not \ - allow cascade persist. Set the cascade attribute for this field to \ - CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or \ - "persist" or "all" (JPA orm.xml), or enable cascade-persist globally, \ - or manually persist the related field value prior to flushing. \ - You cannot flush unmanaged objects or graphs that have persistent \ - associations to unmanaged objects. -cant-cascade-attach: Encountered new object in persistent field \ - "{0}" during attach. However, this field does not \ - allow cascade attach. Set the cascade attribute for this field to \ - CascadeType.MERGE or CascadeType.ALL (JPA annotations) or \ - "merge" or "all" (JPA orm.xml). \ - You cannot attach a reference to a new object without cascading. -ref-to-deleted: Encountered deleted object "{0}" in persistent field \ - "{1}" of managed object "{2}" during flush. -no-version-field: Encountered object "{0}" without a version field during \ - attach. In order to attach an object, it must either be enhanced or must \ - have a version field. -inmem-agg-proj-var: Queries with aggregates or projections using variables \ - currently cannot be executed in-memory. Either set IgnoreCache to true, \ - set the openjpa.FlushBeforeQueries property to true, or execute the query \ - before changing any instances in the transaction. The offending query was \ - on type "{0}" with filter "{1}". -merged-order-with-result: This query on candidate type "{0}" with filter "{1}" \ - involves combining the results of multiple queries in memory. \ - You have chosen to order the results on "{2}", but you have not selected \ - this data in your setResult() clause. Please include this ordering data \ - in setResult() so that OpenJPA can extract it for in-memory ordering. -bad-grouping: Your query on type "{0}" with filter "{1}" is invalid. Your \ - select and having clauses must only include aggregates or values that also \ - appear in your grouping clause. -query-nosupport: The "{0}" query type does not support this operation. -query-unmapped: You cannot query unmapped type "{0}". -range-too-big: The range of the query is too big. Start index: "{0}", end \ - index: "{1}". The range must be less than Integer.MAX_VALUE. -invalid-range: The query range from {0} to {1} is not valid. -no-impls: Unable to execute a query on type "{0}". This class or interface \ - is not mapped, and does not have any mapped implementors. -bad-param-name: The parameter name or position "{0}" passed to \ - execute() is not valid. All map keys must be a declared parameter \ - name or a number matching the parameter position. Native queries only \ - allow the use of positional parameters. -force-in-mem: This query on type "{0}" must load the entire candidate class \ - extent and evaluate the query in-memory. This may be very slow. The \ - query must be executed in memory because OpenJPA is configured with \ - IgnoreCache=false and FlushBeforeQueries=false and \ - there are dirty instances that may affect the query''s outcome in the \ - cache. -cant-exec-inmem: Queries of this type ("{0}") cannot be executed in-memory. \ - Either set IgnoreCache to true, set the openjpa.FlushBeforeQueries \ - property to true, or execute the query before changing any instances in \ - the transaction. -executing-query: Executing query: {0} -executing-query-with-params: Executing query: [{0}] with parameters: {1} -not-unique: The query on candidate type "{0}" with filter "{1}" was \ - configured to have a unique result, but more than one instance matched \ - the query. -no-result: The query on candidate type "{0}" with filter "{1}" was \ - configured to have a unique result, but no instance matched \ - the query. -serialized: Queries that have been serialized do not support this operation. -read-only: Attempt to modify a read-only query object. -no-class: A candidate Class must be specified before executing a query. -no-modify-resultclass: A query that declares a result class cannot be used \ - to perform bulk updates. -no-modify-unique: A query that declares unique results cannot be used \ - to perform bulk updates. -no-modify-range: A query that declares a result range cannot be used \ - to perform bulk updates. -unbound-param: Cannot execute query; the declared parameter "{0}" was \ - not given a value. -unbound-params: Cannot execute query; declared parameters "{0}" were not given \ - values. You must supply a value for each of the following parameters, \ - in the given order: {1} -extra-params: More parameters were passed to execute() than were declared: \ - {1} parameters were specified for query execution, but only {0} \ - parameters were declared in the query. -null-primitive-param: Parameter "{0}" expects a value of primitive "{1}" \ - but was given a null value. -param-value-mismatch: Parameter "{0}" expects a value of "{1}" but was given \ - a value of "{2}" of "{3}". -merged-aggregate: This query on candidate type "{0}" with filter "{1}" \ - involves combining the results of multiple sub-queries. However, because \ - this query is for aggregate data, OpenJPA cannot combine the sub-query \ - aggregates into correct final values. -bad-dec: The {1} declaration "{0}" is \ - not valid. Variables and imports must be delimited with ";". Parameters \ - and orderings must be delimited with ",". Imports require the "import" \ - keyword, and orderings require the "ascending" or "descending" keyword. -mod-bigdecimal: You cannot use the modulo operator (%) on numbers of type \ - BigDecimal. -cant-convert: Cannot convert object "{0}" of type "{1}" into an instance of \ - "{2}". -bad-method-class: You set the method name of this openjpa.MethodQL query to \ - "{1}", but class "{0}" is not a valid class name. Make sure to fully \ - qualify the class name or to import its package into this query if the \ - class is not in the query candidate class'' package. -method-not-static: Method "{0}" named in the MethodQL query must be static. -method-return-type-invalid: Method "{0}" named in the MethodQL query must \ - have a return type that is assignable from ResultObjectProvider. Return \ - type is: {1}. -no-method: You must set the query filter to the name of the method to execute \ - for this MethodQL query instance. -method-error: There was an error invoking method "{0}" with arguments "{1}". -bad-param-type: The type "{0}" as used in the parameter declarations \ - could not be found in the imports. -cant-set: Result type "{0}" does not have any public fields or setter methods \ - for the projection or aggregate result element "{1}", nor does it have a \ - generic put(Object,Object) method that can be used, nor does it have a \ - public constructor that takes the types {2}. -pack-err: There was an error packing the projection and/or aggregate results \ - of the query into result type "{0}". See the nested Throwable exception \ - for details. -pack-instantiation-err: There was an error creating an instance of type "{0}" \ - when packing the projection and/or aggregate results of the query. Ensure \ - that you have defined a public no-args constructor in "{0}". -bad-inmem-method: Method "{0}(StoreContext, ClassMetaData, boolean, Object, \ - Map, FetchConfiguration)" is not declared in type "{1}". \ - Check the method name supplied in your MethodQL query filter. \ - OpenJPA is attempting to execute this query in-memory; if you implemented \ - the datastore method instead (a method with the same signature but without \ - the Object argument) and want this query to execute in the datastore, \ - either create the query before modifying objects in the current transaction, \ - set IgnoreCache to true, or set the openjpa.FlushBeforeQueries property to \ - true. -bad-datastore-method: Method "{0}(StoreContext, ClassMetaData, boolean, Map, \ - FetchConfiguration)" is not declared in type "{1}". Check \ - the method name supplied in your MethodQL query filter. OpenJPA is \ - attempting to execute this query against the datastore; if you implemented \ - the in-memory method instead (a method with the same signature but with an \ - Object argument) and want this query to execute in-memory, supply a \ - Collection of candidates to filter. -only-update-constants: Bulk update queries when executed in memory \ - may only update to constant values. -only-range-constants: Range values must be numeric constants. Illegal query: \ - {0} -no-savepoint-copy: Unable to copy field "{0}" for savepoint. -savepoint-exists: A savepoint with the name "{0}" already exists. \ - Each savepoint name must be unique. -no-lastsavepoint: Cannot rollback/release last savepoint as no savepoint \ - has been set. -no-savepoint: You have not set a savepoint with the name "{0}" -savepoint-init: This savepoint has already been initialized. -savepoint-flush-not-supported: The configured SavepointManager does not \ - support incremental flushing when a savepoint has been set. You must \ - release your savepoints before flushing. -callback-err: Errors occurred processing listener callbacks. See the nested \ - exceptions for details. -bad-agg-listener-hint: Query hint value "{0}" ({1}) cannot be converted into \ - an aggregate listener. -bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \ - into a filter listener. -bad-setter-hint-arg: In query hint "{0}", cannot convert hint value "{1}" to \ - type "{2}". -detach-val-mismatch: The instance "{0}" is managed by another context and \ - cannot be inspected for field values. -detach-val-badsm: The instance "{0}" has an unknown state manager which \ - prevents field inspection. -null-oid: Cannot perform find using null object id. -illegal-op-in-prestore: This operation is illegal when called during \ - transaction completion. -no-expressions: The query cannot be executed because it has no \ - valid expressions. -null-fg: Attempt to add null/empty fetch group name to fetch configuration. -null-field: Attempt to add null/empty field name to fetch configuration. -container-projection: Query projections cannot include array, collection, or \ - map fields. Invalid query: "{0}" -existing-value-override-excep: The generated value processing detected an \ -existing value assigned to this field: {0}. This existing value was either \ -provided via an initializer or by calling the setter method. You either need \ -to remove the @GeneratedValue annotation or modify the code to remove the \ -initializer processing. -invalid-tran-status: The transaction was not in a valid state ({0}) to \ -accept the "{1}" method invocation. Processing will continue. -multi-threaded-access: Multiple concurrent threads attempted to access a \ - single broker. By default brokers are not thread safe; if you require \ - and/or intend a broker to be accessed by more than one thread, set the \ - openjpa.Multithreaded property to true to override the default behavior. -no-saved-fields: No state snapshot is available for instance of type "{0}", \ - but this instance uses state-comparison for dirty detection. -cant-serialize-flushed-broker: Serialization not allowed once a broker has \ - been flushed. -cant-serialize-pessimistic-broker: Serialization not allowed for brokers with \ - an active datastore (pessimistic) transaction. -cant-serialize-connected-broker: Serialization not allowed for brokers with \ - an active connection to the database. -no-interface-metadata: No metadata was found for managed interface {0}. -fetch-configuration-stack-empty: Fetch configuration stack is empty. -gap-query-param: Parameter {1} for query "{0}" exceeds the number of {2} \ - bound parameters with following values "{3}". This can happen if you have \ - declared but missed to bind values for one or more parameters. -query-execution-error: Failed to execute query "{0}". Check the query syntax \ - for correctness. See nested exception for details. -invalid-timeout: An invalid timeout of {0} milliseconds was ignored. \ - Expected a value that is greater than or equal to -1. +# 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. + +cant-convert-result: There is no conversion between query projection type \ + "{0}" and result type "{1}". +unloaded-detached: Attempt to access an unloaded field of detached instance \ + "{0}". +meta-unknownid: Cannot manipulate identity of type "{0}": it''s identity type \ + is unknown. +new-abstract: Cannot create an instance of "{0}": abstract classes are not \ + yet supported. +bad-new-query: Attempt to construct a query from an extent or class. You must \ + pass a (possibly null) query string or template to the query factory \ + method when creating the query. +update-restrict: Detected attempt to modify field "{0}" with value strategy \ + "restrict". +reentrant-flush: Detected reentrant flush. Make sure your flush-time instance \ + callback methods or event listeners do not invoke any operations that \ + require the in-progress flush to complete. +rolled-back: The transaction has been rolled back. See the nested exceptions \ + for details on the errors that occurred. +bad-lock-level: This lock manager does not recognize lock level "{0}". +pessimistic-mutate: You are attempting to directly mutate a persistent second \ + class object (such as a collection or map field) that you obtained before \ + the transaction began. After beginning a datastore transaction, you \ + must re-obtain any references to mutable second class objects from the \ + owning persistent object. Detected attempt to mutate value of field "{0}" \ + in instance "{1}". This instance may not be locked correctly. +not-derefed: Encountered unknown dependent instance "{0}". This error is \ + often caused by either removing a dependent instance from one dependent \ + field, but not other dependent fields that reference it, or by removing a \ + dependent instance from its owning field, flushing \ + (causing the unreferenced dependent instance to be deleted), and then \ + trying to assign the deleted instance to another field before commit. \ + The instance cannot be un-deleted, resulting in an error. Make sure not \ + to leave dangling dependent references to objects, and to reassign \ + dependent objects before flush so that OpenJPA does not think they are \ + unreferenced and therefore safe to delete. +init-null-pc: Attempt to initialize a state manager with a null \ + persistence-capable instance for type "{0}". This is often caused by \ + attempting to load an instance of an abstract class, or \ + neglecting to use a class indicator when the base persistence-capable \ + class in an inheritance tree is abstract. +init-sm-pc: Attempt to initialize a state manager with an instance that is \ + already managed ("{0}"). You might be trying to persist this instance \ + in two threads at the same time. +bad-ds-oid: The type "{0}" declares datastore identity but the value \ + passed to lookup of type "{1}" is not a OpenJPA id instance. +null-oids: Some of the object ids passed to getObjectsById were null. +marked-rollback: The transaction cannot be committed, because it was already \ + marked for rollback only. The transaction will be rolled back instead. \ + The cause of the rollback-only status is reported in the embedded stack. +refresh-flushed: You cannot refresh an instance that has been flushed to the \ + data store. +pc-loader-different: Attempt to cast instance "{0}" to PersistenceCapable failed. \ + The object implemented org.apache.openjpa.enhance.PersistenceCapable, \ + but the instance of that interface was loaded by two different ClassLoaders: \ + "{1}" and "{2}". +pc-cast: Attempt to cast instance "{0}" to PersistenceCapable failed. Ensure \ + that it has been enhanced. +del-instance: The instance of type "{0}" with oid "{1}" no longer exists in \ + the data store. This may mean that you deleted the instance in a separate \ + transaction, but this context still has a cached version. +no-broker-class: The specified type "{0}" could not be loaded. Please ensure \ + that the class exists in the project class path. +bad-embed: Attempt to set an embedded value for unembeddable field "{0}". \ + Please report this error to OpenJPA support. +embed-ref: You are attempting to access an embedded object reference \ + that was obtained before the last transaction status change. After \ + transactions begin and end, all references to embedded objects become \ + invalid; you have to re-acquire the reference from the owning persistent \ + object. +deleted: Operation attempted on a deleted instance. +dirty: Illegal operation attempted on a dirty instance: dirty objects cannot \ + be evicted or made transient or non-transactional. +nested-exceps: This operation failed for some instances. See the nested \ + exceptions array for details. +new: Illegal operation attempted on a newly persisted instance: new objects \ + cannot be evicted or made transient or non-transactional. +transient: Illegal operation attempted on a transient instance. +not-active: Can only perform operation while a transaction is active. +trans-active: The "{0}" transaction property cannot be set during an \ + active transaction. +active: This operation cannot be performed while a Transaction is active. +closed: The context has been closed. The stack trace at which the \ + context was closed is held in the embedded exception. +closed-notrace: The context has been closed. The stack trace at which the \ + context was closed is available if Runtime=TRACE logging is enabled. +closed-factory: The factory has been closed. The stack trace at \ + which the factory was closed is held in the embedded exception. +closed-factory-notrace: The factory has been closed. The stack trace at \ + which the factory was closed is available if Runtime=TRACE logging is \ + enabled. +non-trans-read: To perform reads on persistent data outside of a transaction, \ + the "NontransactionalRead" property must be set on the Transaction. +non-trans-write: To perform writes on persistent data outside of a \ + transaction, the "NontransactionalWrite" property must be set to true. +write-operation: To perform this operation, it must be written within a transaction, \ + or your settings must allow nontransactional writes and must not detach \ + all nontransactional reads. +not-managed: The given instance "{0}" is not managed by this context. +trans-not-managed: This broker is not configured to use managed transactions. +bad-detached-op: You cannot perform operation {0} on detached object "{1}". \ + This operation only applies to managed objects. +persist-detached: Attempt to persist detached object "{0}". If this is a new \ + instance, make sure any version and/or auto-generated primary key fields are \ + null/default when persisting. +null-value: The field "{0}" of instance "{1}" contained a null value; \ + the metadata for this field specifies that nulls are illegal. +change-identity: Attempt to change a primary key field of an instance that \ + already has a final object id. Only new, unflushed instances whose id you \ + have not retrieved can have their primary keys changed. +managed-oid: You cannot assign managed object "{0}" to the primary key field \ + of "{1}". Embedded primary key values must be transient objects. +changed-oid: You have modified the object id field of "{2}". Its old value \ + was "{0}", and its new value is "{1}". Object id fields are immutable \ + once the object id of the instance has been assigned. +cache-exists: An object of type "{0}" with oid "{1}" already exists in this \ + context; another cannot be persisted. +null-trans: Attempt to commit a null javax.transaction.Transaction. Some \ + application servers set the transaction to null if a rollback occurs. +end-trans-error: An exception occurred while ending the transaction. This \ + exception will be re-thrown. +not-bound: The file named "{0}" could not be found. +naming-exception: A NamingException was thrown while obtaining the \ + factory at "{0}" from JNDI. +attach-deleted: The object "{0}" with id "{1}" has been deleted and \ + cannot be attached. +not-detachable: The class "{0}" does not declare the "detachable" metadata \ + extension, so cannot be detached. +not-copyable: Attempt to copy field "{0}" failed. The field is \ + not copyable. This can occur with custom SCO types. Only standard or \ + immutable SCO types can be attached and detached. +no-detach-object-id: Cannot access the detached object id of class "{0}". \ + Ensure that the class has the "detachable" metadata extension, and \ + the the class has been re-enhanced. +attach-version-del: Attempted to attach deleted instance type "{0}" with oid \ + "{1}". If the instance is new, the version field should be left to its \ + default value. +attach-wrongclass: Attempted to attach instance "{0}" of type "{1}", but this \ + instance is already in the datastore as type "{2}". +sjvm-acquired-lock: Acquired an exclusive lock "{0}" on oid "{1}". +sjvm-released-lock: Released lock "{0}". +conn-not-supported: This data store cannot return connections. +incremental-flush-not-supported: This data store does not support incremental \ + flushing. If you got this error while performing a query, make sure that \ + you have not set the FlushBeforeQueries option to true, either by \ + setting that option in your configuration file, or by programmatically \ + setting the current FetchConfiguration''s FlushBeforeQueries property \ + to QueryFlushModes.FLUSH_TRUE. +nontrans-read-not-supported: This data store does not support nontransactional \ + reads. Set the NontransactionalRead property to false. +optimistic-not-supported: This datastore does not support optimistic \ + transactions. Set the Optimistic property to false. +restore-unset: The RestoreValues option is off, so initial values are \ + not available. Turn on RestoreValues to be able to obtain initial \ + values. +mutable-restore-unset: The RestoreValues option is not set to "all", \ + initial values of mutable fields are not available. Set RestoreValues to \ + "all" in your properties to be able to obtain initial mutable values. +initial-unloaded: OpenJPA cannot provide the initial value for field "{0}" \ + because the field was never loaded before being changed. +dup-oid-assign: Attempt to assign id "{0}" to new instance "{1}" failed; \ + there is already an object in the L1 cache with this id. \ + You must delete this object (in a previous transaction or the current one) \ + before reusing its id. This error can also occur when a horizontally \ + or vertically mapped classes uses auto-increment application identity and \ + does not use a hierarchy of application identity classes. +dup-load: Cannot load object with id "{0}". Instance "{1}" with the same id \ + already exists in the L1 cache. This can occur when you \ + assign an existing id to a new instance, and before flushing attempt to \ + load the existing instance for that id. +bad-id-value: The given value "{0}" cannot be converted into an identity \ + for "{2}". The value is the wrong type ({1}). +factory-init: Starting OpenJPA {0} +factory-properties: Properties: {0} +inverse-consistency: An inverse inconsistency in the object model was \ + detected while flushing the field "{0}" of the instance with id "{1}" \ + in context "{2}". +no-brokerfactory: You did not name the factory class with the required \ + property openjpa.BrokerFactory. Normally this property defaults \ + appropriately; have you forgotten to include all the OpenJPA jars in your \ + classpath? +brokerfactory-excep: There was an error when invoking the static \ + getInstance method on the named factory class "{0}". See the \ + nested exception for details. +new-brokerfactory-excep: There was an error when invoking the static \ + newInstance method on the named factory class "{0}". See the \ + nested exception for details. +bad-brokerfactory: Could not invoke the static getInstance method on the \ + named factory class "{0}". +bad-new-brokerfactory: Could not invoke the static newInstance method on the \ + named factory class "{0}". +bad-brokerfactory-class: The named BrokerFactory "{0}" is not valid. +instantiate-abstract: Cannot instantiate abstract class of type "{0}" with \ + object id "{1}"; this may indicate that the inheritance discriminator \ + for the class is not configured correctly. +nontrans-proxied: You cannot make a property access object created with "new" \ + nontransactional. +no-field: Field "{0}" is not declared in "{1}", or is not managed. +no-field-index: "{0}" is not the index of any managed field in "{1}". +cant-cascade-persist: Encountered unmanaged object in persistent field \ + "{0}" during flush. However, this field does not \ + allow cascade persist. Set the cascade attribute for this field to \ + CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or \ + "persist" or "all" (JPA orm.xml), or enable cascade-persist globally, \ + or manually persist the related field value prior to flushing. \ + You cannot flush unmanaged objects or graphs that have persistent \ + associations to unmanaged objects. +cant-cascade-attach: Encountered new object in persistent field \ + "{0}" during attach. However, this field does not \ + allow cascade attach. Set the cascade attribute for this field to \ + CascadeType.MERGE or CascadeType.ALL (JPA annotations) or \ + "merge" or "all" (JPA orm.xml). \ + You cannot attach a reference to a new object without cascading. +ref-to-deleted: Encountered deleted object "{0}" in persistent field \ + "{1}" of managed object "{2}" during flush. +no-version-field: Encountered object "{0}" without a version field during \ + attach. In order to attach an object, it must either be enhanced or must \ + have a version field. +inmem-agg-proj-var: Queries with aggregates or projections using variables \ + currently cannot be executed in-memory. Either set IgnoreCache to true, \ + set the openjpa.FlushBeforeQueries property to true, or execute the query \ + before changing any instances in the transaction. The offending query was \ + on type "{0}" with filter "{1}". +merged-order-with-result: This query on candidate type "{0}" with filter "{1}" \ + involves combining the results of multiple queries in memory. \ + You have chosen to order the results on "{2}", but you have not selected \ + this data in your setResult() clause. Please include this ordering data \ + in setResult() so that OpenJPA can extract it for in-memory ordering. +bad-grouping: Your query on type "{0}" with filter "{1}" is invalid. Your \ + select and having clauses must only include aggregates or values that also \ + appear in your grouping clause. +query-nosupport: The "{0}" query type does not support this operation. +query-unmapped: You cannot query unmapped type "{0}". +range-too-big: The range of the query is too big. Start index: "{0}", end \ + index: "{1}". The range must be less than Integer.MAX_VALUE. +invalid-range: The query range from {0} to {1} is not valid. +no-impls: Unable to execute a query on type "{0}". This class or interface \ + is not mapped, and does not have any mapped implementors. +bad-param-name: The parameter name or position "{0}" passed to \ + execute() is not valid. All map keys must be a declared parameter \ + name or a number matching the parameter position. Native queries only \ + allow the use of positional parameters. +force-in-mem: This query on type "{0}" must load the entire candidate class \ + extent and evaluate the query in-memory. This may be very slow. The \ + query must be executed in memory because OpenJPA is configured with \ + IgnoreCache=false and FlushBeforeQueries=false and \ + there are dirty instances that may affect the query''s outcome in the \ + cache. +cant-exec-inmem: Queries of this type ("{0}") cannot be executed in-memory. \ + Either set IgnoreCache to true, set the openjpa.FlushBeforeQueries \ + property to true, or execute the query before changing any instances in \ + the transaction. +executing-query: Executing query: {0} +executing-query-with-params: Executing query: [{0}] with parameters: {1} +not-unique: The query on candidate type "{0}" with filter "{1}" was \ + configured to have a unique result, but more than one instance matched \ + the query. +no-result: The query on candidate type "{0}" with filter "{1}" was \ + configured to have a unique result, but no instance matched \ + the query. +serialized: Queries that have been serialized do not support this operation. +read-only: Attempt to modify a read-only query object. +no-class: A candidate Class must be specified before executing a query. +no-modify-resultclass: A query that declares a result class cannot be used \ + to perform bulk updates. +no-modify-unique: A query that declares unique results cannot be used \ + to perform bulk updates. +no-modify-range: A query that declares a result range cannot be used \ + to perform bulk updates. +unbound-param: Cannot execute query; the declared parameter "{0}" was \ + not given a value. +unbound-params: Cannot execute query; declared parameters "{0}" were not given \ + values. You must supply a value for each of the following parameters, \ + in the given order: {1} +extra-params: More parameters were passed to execute() than were declared: \ + {1} parameters were specified for query execution, but only {0} \ + parameters were declared in the query. +null-primitive-param: Parameter "{0}" expects a value of primitive "{1}" \ + but was given a null value. +param-value-mismatch: Parameter "{0}" expects a value of "{1}" but was given \ + a value of "{2}" of "{3}". +merged-aggregate: This query on candidate type "{0}" with filter "{1}" \ + involves combining the results of multiple sub-queries. However, because \ + this query is for aggregate data, OpenJPA cannot combine the sub-query \ + aggregates into correct final values. +bad-dec: The {1} declaration "{0}" is \ + not valid. Variables and imports must be delimited with ";". Parameters \ + and orderings must be delimited with ",". Imports require the "import" \ + keyword, and orderings require the "ascending" or "descending" keyword. +mod-bigdecimal: You cannot use the modulo operator (%) on numbers of type \ + BigDecimal. +cant-convert: Cannot convert object "{0}" of type "{1}" into an instance of \ + "{2}". +bad-method-class: You set the method name of this openjpa.MethodQL query to \ + "{1}", but class "{0}" is not a valid class name. Make sure to fully \ + qualify the class name or to import its package into this query if the \ + class is not in the query candidate class'' package. +method-not-static: Method "{0}" named in the MethodQL query must be static. +method-return-type-invalid: Method "{0}" named in the MethodQL query must \ + have a return type that is assignable from ResultObjectProvider. Return \ + type is: {1}. +no-method: You must set the query filter to the name of the method to execute \ + for this MethodQL query instance. +method-error: There was an error invoking method "{0}" with arguments "{1}". +bad-param-type: The type "{0}" as used in the parameter declarations \ + could not be found in the imports. +cant-set: Result type "{0}" does not have any public fields or setter methods \ + for the projection or aggregate result element "{1}", nor does it have a \ + generic put(Object,Object) method that can be used, nor does it have a \ + public constructor that takes the types {2}. +pack-err: There was an error packing the projection and/or aggregate results \ + of the query into result type "{0}". See the nested Throwable exception \ + for details. +pack-instantiation-err: There was an error creating an instance of type "{0}" \ + when packing the projection and/or aggregate results of the query. Ensure \ + that you have defined a public no-args constructor in "{0}". +bad-inmem-method: Method "{0}(StoreContext, ClassMetaData, boolean, Object, \ + Map, FetchConfiguration)" is not declared in type "{1}". \ + Check the method name supplied in your MethodQL query filter. \ + OpenJPA is attempting to execute this query in-memory; if you implemented \ + the datastore method instead (a method with the same signature but without \ + the Object argument) and want this query to execute in the datastore, \ + either create the query before modifying objects in the current transaction, \ + set IgnoreCache to true, or set the openjpa.FlushBeforeQueries property to \ + true. +bad-datastore-method: Method "{0}(StoreContext, ClassMetaData, boolean, Map, \ + FetchConfiguration)" is not declared in type "{1}". Check \ + the method name supplied in your MethodQL query filter. OpenJPA is \ + attempting to execute this query against the datastore; if you implemented \ + the in-memory method instead (a method with the same signature but with an \ + Object argument) and want this query to execute in-memory, supply a \ + Collection of candidates to filter. +only-update-constants: Bulk update queries when executed in memory \ + may only update to constant values. +only-range-constants: Range values must be numeric constants. Illegal query: \ + {0} +no-savepoint-copy: Unable to copy field "{0}" for savepoint. +savepoint-exists: A savepoint with the name "{0}" already exists. \ + Each savepoint name must be unique. +no-lastsavepoint: Cannot rollback/release last savepoint as no savepoint \ + has been set. +no-savepoint: You have not set a savepoint with the name "{0}" +savepoint-init: This savepoint has already been initialized. +savepoint-flush-not-supported: The configured SavepointManager does not \ + support incremental flushing when a savepoint has been set. You must \ + release your savepoints before flushing. +callback-err: Errors occurred processing listener callbacks. See the nested \ + exceptions for details. +bad-agg-listener-hint: Query hint value "{0}" ({1}) cannot be converted into \ + an aggregate listener. +bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \ + into a filter listener. +bad-setter-hint-arg: In query hint "{0}", cannot convert hint value "{1}" to \ + type "{2}". +detach-val-mismatch: The instance "{0}" is managed by another context and \ + cannot be inspected for field values. +detach-val-badsm: The instance "{0}" has an unknown state manager which \ + prevents field inspection. +null-oid: Cannot perform find using null object id. +illegal-op-in-prestore: This operation is illegal when called during \ + transaction completion. +no-expressions: The query cannot be executed because it has no \ + valid expressions. +null-fg: Attempt to add null/empty fetch group name to fetch configuration. +null-field: Attempt to add null/empty field name to fetch configuration. +container-projection: Query projections cannot include array, collection, or \ + map fields. Invalid query: "{0}" +existing-value-override-excep: The generated value processing detected an \ +existing value assigned to this field: {0}. This existing value was either \ +provided via an initializer or by calling the setter method. You either need \ +to remove the @GeneratedValue annotation or modify the code to remove the \ +initializer processing. +invalid-tran-status: The transaction was not in a valid state ({0}) to \ +accept the "{1}" method invocation. Processing will continue. +multi-threaded-access: Multiple concurrent threads attempted to access a \ + single broker. By default brokers are not thread safe; if you require \ + and/or intend a broker to be accessed by more than one thread, set the \ + openjpa.Multithreaded property to true to override the default behavior. +no-saved-fields: No state snapshot is available for instance of type "{0}", \ + but this instance uses state-comparison for dirty detection. +cant-serialize-flushed-broker: Serialization not allowed once a broker has \ + been flushed. +cant-serialize-pessimistic-broker: Serialization not allowed for brokers with \ + an active datastore (pessimistic) transaction. +cant-serialize-connected-broker: Serialization not allowed for brokers with \ + an active connection to the database. +no-interface-metadata: No metadata was found for managed interface {0}. +fetch-configuration-stack-empty: Fetch configuration stack is empty. +gap-query-param: Parameter {1} for query "{0}" exceeds the number of {2} \ + bound parameters with following values "{3}". This can happen if you have \ + declared but missed to bind values for one or more parameters. +query-execution-error: Failed to execute query "{0}". Check the query syntax \ + for correctness. See nested exception for details. +invalid-timeout: An invalid timeout of {0} milliseconds was ignored. \ + Expected a value that is greater than or equal to -1. +bad-hint-value: "{1}" is not a valid value for hint "{0}" caused by: {2}. +bad-flush-before-queries: Invalid flush before queries type. Valid values are \ + "true"(0), "false"(1) or "with-connection"(2). Specified value: {0}. +bad-lock-level: Invalid lock mode/level. Valid values are \ + "none"(0), "read"(10), "write"(20), "optimistic"(10), \ + "optimistic-force-increment"(20), "pessimistic-read"(30), \ + "pessimistic-write"(40) or "pessimistic-force-increment"(50). \ + Specified value: {0}. diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java index 1762607b4..5c457750f 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java @@ -104,8 +104,6 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase { } } assertAllSQLInOrder( - "INSERT INTO " + empTableName + " .*", - "INSERT INTO " + empTableName + " .*", "INSERT INTO " + empTableName + " .*"); // dynamic runtime test to determine wait time. @@ -150,6 +148,8 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase { em.createQuery("delete from " + empTableName).executeUpdate(); em.getTransaction().commit(); + } catch(Exception e) { + e.printStackTrace(); } finally { if (em != null && em.isOpen()) { em.close(); @@ -607,9 +607,10 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase { LockModeType expectedlockMode = (LockModeType)args[2]; LockModeType testinglockMode = em.getLockMode(employee); log.trace("test version: expected=" + expectedlockMode - + ", testing=" + em.getLockMode(employee)); + + ", testing=" + testinglockMode); - assertEquals("", expectedlockMode, testinglockMode); + assertEquals("", getCanonical(expectedlockMode), + getCanonical(testinglockMode)); break; case ResetException: thisThread.throwable = null; @@ -825,6 +826,14 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase { } } + private LockModeType getCanonical(LockModeType lockMode) { + if( lockMode == LockModeType.READ ) + return LockModeType.OPTIMISTIC; + if( lockMode == LockModeType.WRITE ) + return LockModeType.OPTIMISTIC_FORCE_INCREMENT; + return lockMode; + } + private String processException(Act curAction, Throwable t) { String failStr = "Caught exception: none"; if (t != null) { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockMode.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockMode.java new file mode 100644 index 000000000..e9913c523 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockMode.java @@ -0,0 +1,264 @@ +/* + * 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.persistence.lockmgr; + +import javax.persistence.EntityManager; +import javax.persistence.LockModeType; + +import org.apache.openjpa.jdbc.conf.JDBCConfiguration; +import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl; +import org.apache.openjpa.jdbc.sql.DB2Dictionary; +import org.apache.openjpa.jdbc.sql.DBDictionary; +import org.apache.openjpa.persistence.EntityManagerImpl; +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; + +/** + * Test hints using EntityManager interface. + */ +public class TestEmLockMode extends SequencedActionsTest { + private static String NON_SUPPORTED_OPTIMISTIC_SQL = + "SELECT .* FROM LockEmployee .*"; + private static String NON_SUPPORTED_FOR_UPDATE_SQL = + "SELECT .* FROM LockEmployee .* FOR UPDATE.*"; + private static String VERSION_UPDATE_SQL = + "UPDATE LockEmployee SET version .* WHERE .*"; + private static String DB2_OPTIMISTIC_SQL = + "SELECT .* FROM LockEmployee .* WHERE .*"; + private static String DB2_PESSIMISTIC_RS_SQL = + "SELECT .* FROM LockEmployee .* WITH RS USE .*"; + private static String DB2_PESSIMISTIC_RR_SQL = + "SELECT .* FROM LockEmployee .* WITH RR USE .*"; + + public void setUp() { + setUp(LockEmployee.class, "openjpa.LockManager", "mixed"); + commonSetUp(); + } + + /* + * Test em.find(lockmode); + */ + public void testFindLockModeIsolations() { + EntityManager em = emf.createEntityManager(); + + em.getTransaction().begin(); + + commonTestFindLockModeIsolations(em, LockModeType.NONE, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 0, null); + commonTestFindLockModeIsolations(em, LockModeType.READ, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestFindLockModeIsolations(em, LockModeType.WRITE, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + VERSION_UPDATE_SQL); + commonTestFindLockModeIsolations(em, LockModeType.OPTIMISTIC, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestFindLockModeIsolations(em, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, 1, DB2_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL, 1, VERSION_UPDATE_SQL); + commonTestFindLockModeIsolations(em, LockModeType.PESSIMISTIC_READ, 2, + DB2_PESSIMISTIC_RS_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestFindLockModeIsolations(em, LockModeType.PESSIMISTIC_WRITE, 2, + DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestFindLockModeIsolations(em, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, 2, + DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + VERSION_UPDATE_SQL); + + em.getTransaction().rollback(); + em.close(); + } + + private void commonTestFindLockModeIsolations(EntityManager em, + LockModeType lockMode, int expectedSupportSQLCount, + String expectedSupportSQL, int expectedNonSupportSQLCount, + String expectedNonSupportSQL, int expectedVersionUpdateCount, + String expectedVersionUpdateSQL) { + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + DBDictionary dict = ((JDBCConfiguration) ((OpenJPAEntityManagerSPI) oem) + .getConfiguration()).getDBDictionaryInstance(); + + em.clear(); + resetSQL(); + int beforeIsolation = fConfig.getIsolation(); + em.find(LockEmployee.class, 1, lockMode); + if (dict.supportsIsolationForUpdate() && + dict instanceof DB2Dictionary) { + assertEquals(expectedSupportSQLCount, getSQLCount()); + assertAllSQLInOrder(expectedSupportSQL); + } else { + assertEquals(expectedNonSupportSQLCount, getSQLCount()); + assertAllSQLInOrder(expectedNonSupportSQL); + } + + resetSQL(); + em.flush(); + assertEquals(expectedVersionUpdateCount, getSQLCount()); + if (expectedVersionUpdateSQL != null) + assertAllSQLInOrder(expectedVersionUpdateSQL); + + assertEquals(beforeIsolation, fConfig.getIsolation()); + } + + /* + * Test em.refresh(lockmode); + */ + public void testRefreshLockModeIsolations() { + EntityManager em = emf.createEntityManager(); + + em.getTransaction().begin(); + + commonTestRefreshLockModeIsolations(em, LockModeType.NONE, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 0, null); + commonTestRefreshLockModeIsolations(em, LockModeType.READ, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestRefreshLockModeIsolations(em, LockModeType.WRITE, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + VERSION_UPDATE_SQL); + commonTestRefreshLockModeIsolations(em, LockModeType.OPTIMISTIC, 1, + DB2_OPTIMISTIC_SQL, 1, NON_SUPPORTED_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestRefreshLockModeIsolations(em, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, 1, DB2_OPTIMISTIC_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL, 1, VERSION_UPDATE_SQL); + commonTestRefreshLockModeIsolations(em, LockModeType.PESSIMISTIC_READ, + 2, DB2_PESSIMISTIC_RS_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestRefreshLockModeIsolations(em, LockModeType.PESSIMISTIC_WRITE, + 2, DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestRefreshLockModeIsolations(em, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, 2, + DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + VERSION_UPDATE_SQL); + + em.getTransaction().rollback(); + em.close(); + } + + private void commonTestRefreshLockModeIsolations(EntityManager em, + LockModeType lockMode, int expectedSupportSQLCount, + String expectedSupportSQL, int expectedNonSupportSQLCount, + String expectedNonSupportSQL, int expectedVersionUpdateCount, + String expectedVersionUpdateSQL) { + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + DBDictionary dict = ((JDBCConfiguration) ((OpenJPAEntityManagerSPI) oem) + .getConfiguration()).getDBDictionaryInstance(); + + em.clear(); + LockEmployee employee = em.find(LockEmployee.class, 1); + resetSQL(); + int beforeIsolation = fConfig.getIsolation(); + em.refresh(employee, lockMode); + if (dict.supportsIsolationForUpdate() && + dict instanceof DB2Dictionary) { + assertEquals(expectedSupportSQLCount, getSQLCount()); + assertAllSQLInOrder(expectedSupportSQL); + } else { + assertEquals(expectedNonSupportSQLCount, getSQLCount()); + assertAllSQLInOrder(expectedNonSupportSQL); + } + + resetSQL(); + em.flush(); + assertEquals(expectedVersionUpdateCount, getSQLCount()); + if (expectedVersionUpdateSQL != null) + assertAllSQLInOrder(expectedVersionUpdateSQL); + + assertEquals(beforeIsolation, fConfig.getIsolation()); + } + + /* + * Test em.lock(lockmode); + */ + public void testLockLockModeIsolations() { + EntityManager em = emf.createEntityManager(); + + em.getTransaction().begin(); + + commonTestLockLockModeIsolations(em, LockModeType.NONE, 0, null, 0, + null, 0, null); + commonTestLockLockModeIsolations(em, LockModeType.READ, 0, null, 0, + null, 1, NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestLockLockModeIsolations(em, LockModeType.WRITE, 0, null, 0, + null, 1, VERSION_UPDATE_SQL); + commonTestLockLockModeIsolations(em, LockModeType.OPTIMISTIC, 0, null, + 0, null, 1, NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestLockLockModeIsolations(em, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, 0, null, 0, null, 1, + VERSION_UPDATE_SQL); + commonTestLockLockModeIsolations(em, LockModeType.PESSIMISTIC_READ, 2, + DB2_PESSIMISTIC_RS_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestLockLockModeIsolations(em, LockModeType.PESSIMISTIC_WRITE, 2, + DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + NON_SUPPORTED_OPTIMISTIC_SQL); + commonTestLockLockModeIsolations(em, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, 2, + DB2_PESSIMISTIC_RR_SQL, 2, NON_SUPPORTED_FOR_UPDATE_SQL, 1, + VERSION_UPDATE_SQL); + + em.getTransaction().rollback(); + em.close(); + } + + private void commonTestLockLockModeIsolations(EntityManager em, + LockModeType lockMode, int expectedSupportSQLCount, + String expectedSupportSQL, int expectedNonSupportSQLCount, + String expectedNonSupportSQL, int expectedVersionUpdateCount, + String expectedVersionUpdateSQL) { + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + DBDictionary dict = ((JDBCConfiguration) ((OpenJPAEntityManagerSPI) oem) + .getConfiguration()).getDBDictionaryInstance(); + + em.clear(); + LockEmployee employee = em.find(LockEmployee.class, 1); + resetSQL(); + int beforeIsolation = fConfig.getIsolation(); + em.lock(employee, lockMode); + if (dict.supportsIsolationForUpdate() && + dict instanceof DB2Dictionary) { + assertEquals(expectedSupportSQLCount, getSQLCount()); + if (expectedSupportSQL != null) + assertAllSQLInOrder(expectedSupportSQL); + } else { + assertEquals(expectedNonSupportSQLCount, getSQLCount()); + if (expectedNonSupportSQL != null) + assertAllSQLInOrder(expectedNonSupportSQL); + } + + resetSQL(); + em.flush(); + assertEquals(expectedVersionUpdateCount, getSQLCount()); + if (expectedVersionUpdateSQL != null) + assertAllSQLInOrder(expectedVersionUpdateSQL); + + assertEquals(beforeIsolation, fConfig.getIsolation()); + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockTimeout.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockTimeout.java new file mode 100644 index 000000000..92577b772 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestEmLockTimeout.java @@ -0,0 +1,111 @@ +/* + * 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.persistence.lockmgr; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.EntityManager; + +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan; +import org.apache.openjpa.persistence.test.AllowFailure; + +/** + * Test hints using EntityManager interface. + */ +public class TestEmLockTimeout extends SequencedActionsTest { + + public void setUp() { + setUp(LockEmployee.class + , "openjpa.LockManager", "mixed" + ); + commonSetUp(); + emf.close(); + } + + /* + * Test setting lock.timeout at the createEntityManagerFactory. + */ + public void testSetJavaxLockTimeoutAtProviderCreateEmf() { + setUp(LockEmployee.class + , "openjpa.LockManager", "mixed" + , "javax.persistence.lock.timeout", "13" + ); + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + + int lockTmo1 = fPlan.getLockTimeout(); + assertEquals(13, lockTmo1); + + em.close(); + emf.close(); + } + + /* + * Test setting lock.timeout at the createEntityManagerFactory, + * with multiple equivalent entries. + */ + @AllowFailure(message="OPENJPA-??? - Provider.createEntityManagerFactory" + + " does not suppport multiple equivalent properties.") + public void testSetLockTimeoutsAtProviderCreateEmf() { + setUp(LockEmployee.class + , "openjpa.LockManager", "mixed" + , "openjpa.LockTimeout", 122 + , "javax.persistence.lock.timeout", "133" + ); + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + + int lockTmo1 = fPlan.getLockTimeout(); + assertEquals(133, lockTmo1); + + em.close(); + emf.close(); + } + + /* + * Test setting lock.timeout at the em.find(), overriding + * value set at createEntityManagerFactory and createEm. + */ + public void testSetJavaxLockTimeoutAtFind() { + setUp(LockEmployee.class + , "openjpa.LockManager", "mixed" + , "javax.persistence.lock.timeout", "13" + ); + + EntityManager em = emf.createEntityManager(); + + Map props2 = new HashMap(); + props2.put("javax.persistence.lock.timeout", 3333); + em.find(LockEmployee.class, 1, props2); + + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + int lockTmo3 = fPlan.getLockTimeout(); + assertEquals(13, lockTmo3); + + em.close(); + emf.close(); + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestFetchHints.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestFetchHints.java new file mode 100644 index 000000000..904588497 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestFetchHints.java @@ -0,0 +1,2464 @@ +/* + * 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.persistence.lockmgr; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.util.HashMap; + +import javax.persistence.EntityManager; +import javax.persistence.LockModeType; +import javax.persistence.Query; + +import org.apache.openjpa.conf.OpenJPAConfiguration; +import org.apache.openjpa.jdbc.conf.JDBCConfiguration; +import org.apache.openjpa.jdbc.kernel.EagerFetchModes; +import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl; +import org.apache.openjpa.jdbc.kernel.LRSSizes; +import org.apache.openjpa.jdbc.sql.JoinSyntaxes; +import org.apache.openjpa.kernel.FetchConfiguration; +import org.apache.openjpa.kernel.MixedLockLevels; +import org.apache.openjpa.kernel.QueryFlushModes; +import org.apache.openjpa.persistence.EntityManagerImpl; +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.jdbc.FetchDirection; +import org.apache.openjpa.persistence.jdbc.FetchMode; +import org.apache.openjpa.persistence.jdbc.IsolationLevel; +import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan; +import org.apache.openjpa.persistence.jdbc.JoinSyntax; +import org.apache.openjpa.persistence.jdbc.LRSSizeAlgorithm; +import org.apache.openjpa.persistence.jdbc.ResultSetType; + +/** + * Test FetchPlan and FetchConfiguration hints processing for use in + * JPA 2.0 em.find/refresh/lock(... Map) and query.X(... Map) methods. + * + * Supported hints: + * javax.persistence.lock.timeout + * javax.persistence.query.timeout + * openjpa.ExtendedPathLookup (?) + * openjpa.FetchBatchSize + * openjpa.FetchPlan.EagerFetchMode + * openjpa.FetchPlan.ExtendedPathLookup (?) + * openjpa.FetchPlan.FetchBatchSize + * openjpa.FetchPlan.FetchDirection + * openjpa.FetchPlan.Isolation + * openjpa.FetchPlan.JoinSyntax + * openjpa.FetchPlan.LRSSize + * openjpa.FetchPlan.LRSSizeAlgorithm + * openjpa.FetchPlan.LockTimeout + * openjpa.FetchPlan.MaxFetchDepth + * openjpa.FetchPlan.QueryTimeout + * openjpa.FetchPlan.ReadLockMode + * openjpa.FetchPlan.ResultSetType + * openjpa.FetchPlan.SubclassFetchMode + * openjpa.FetchPlan.WriteLockMode + * openjpa.FlushBeforeQueries + * openjpa.LockTimeout + * openjpa.MaxFetchDepth + * openjpa.QueryCacheEnabled + * openjpa.QueryTimeout + * openjpa.ReadLockLevel + * openjpa.WriteLockLevel + * openjpa.jdbc.EagerFetchMode + * openjpa.jdbc.FetchDirection + * openjpa.jdbc.JoinSyntax + * openjpa.jdbc.LRSSize + * openjpa.jdbc.ResultSetType + * openjpa.jdbc.SubclassFetchMode + * openjpa.jdbc.TransactionIsolation + */ +public class TestFetchHints extends SequencedActionsTest { + public void setUp() { + setUp(LockEmployee.class + , "openjpa.LockManager", "mixed" + ); + commonSetUp(); + } + + /* Good + * Test "openjpa.FetchBatchSize" hint + */ + public void testFetchBatchSizeHint() { + String hintName = "openjpa.FetchBatchSize"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + fetchBatchSizeHintTest(fPlan, fConfig, hintName, "-1", -1); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, -1, -1); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, "100", 100); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, 100, 100); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "xxxxx", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setFetchBatchSize(999); + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(fPlan.getFetchBatchSize(), -1); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "openjpa.FetchPlan.FetchBatchSize" hint + */ + public void testFetchPlanFetchBatchSizeHint() { + String hintName = "openjpa.FetchPlan.FetchBatchSize"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + fetchBatchSizeHintTest(fPlan, fConfig, hintName, "0", 0); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, 0, 0); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, "500", 500); + fetchBatchSizeHintTest(fPlan, fConfig, hintName, 500, 500); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setFetchBatchSize(999); + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(fPlan.getFetchBatchSize(), -1); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void fetchBatchSizeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + int expected) { + fConfig.setFetchBatchSize(999); + fPlan.setHint(hint, value, false); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expected, fPlan.getFetchBatchSize()); + assertEquals(expected, fConfig.getFetchBatchSize()); + } + + /* Good + * Test "openjpa.FetchPlan.EagerFetchMode" hint + */ + public void testFetchPlanEagerFetchModeHint() { + String hintName = "openjpa.FetchPlan.EagerFetchMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, "none", + FetchMode.NONE, EagerFetchModes.EAGER_NONE); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.NONE.name(), + FetchMode.NONE, EagerFetchModes.EAGER_NONE); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.NONE, + FetchMode.NONE, EagerFetchModes.EAGER_NONE); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, "parallel", + FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.PARALLEL + .name(), FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.PARALLEL, + FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, "join", + FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.JOIN.name(), + FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + eagerFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.JOIN, + FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.EagerFetchMode" hint + */ + public void testJdbcEagerFetchModeHint() { + String hintName = "openjpa.jdbc.EagerFetchMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_NONE), FetchMode.NONE, + EagerFetchModes.EAGER_NONE); + eagerFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_NONE, FetchMode.NONE, + EagerFetchModes.EAGER_NONE); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_PARALLEL, FetchMode.PARALLEL, + EagerFetchModes.EAGER_PARALLEL); + eagerFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_PARALLEL), FetchMode.PARALLEL, + EagerFetchModes.EAGER_PARALLEL); + + eagerFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_JOIN), FetchMode.JOIN, + EagerFetchModes.EAGER_JOIN); + eagerFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_JOIN, FetchMode.JOIN, + EagerFetchModes.EAGER_JOIN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(fPlan.getEagerFetchMode(), FetchMode.PARALLEL); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + + em.close(); + } + + private void eagerFetchModeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getEagerFetchMode()); + assertEquals(expected, fConfig.getEagerFetchMode()); + } + + /* Good + * Test "openjpa.FetchPlan.JoinSyntax" hint + */ + public void testFetchPlanJoinSyntaxHint() { + String hintName = "openjpa.FetchPlan.JoinSyntax"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + joinSyntaxHintTest(fPlan, fConfig, hintName, "sql92", + JoinSyntax.SQL92, JoinSyntaxes.SYNTAX_SQL92); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntax.SQL92.name(), + JoinSyntax.SQL92, JoinSyntaxes.SYNTAX_SQL92); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntax.SQL92, + JoinSyntax.SQL92, JoinSyntaxes.SYNTAX_SQL92); + + joinSyntaxHintTest(fPlan, fConfig, hintName, "traditional", + JoinSyntax.TRADITIONAL, JoinSyntaxes.SYNTAX_TRADITIONAL); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntax.TRADITIONAL + .name(), JoinSyntax.TRADITIONAL, JoinSyntaxes.SYNTAX_TRADITIONAL); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntax.TRADITIONAL, + JoinSyntax.TRADITIONAL, JoinSyntaxes.SYNTAX_TRADITIONAL); + + joinSyntaxHintTest(fPlan, fConfig, hintName, "database", + JoinSyntax.DATABASE, JoinSyntaxes.SYNTAX_DATABASE); + joinSyntaxHintTest(fPlan, fConfig, hintName, + JoinSyntax.DATABASE.name(), JoinSyntax.DATABASE, + JoinSyntaxes.SYNTAX_DATABASE); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntax.DATABASE, + JoinSyntax.DATABASE, JoinSyntaxes.SYNTAX_DATABASE); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.JoinSyntax" hint + */ + public void testJdbcJoinSyntaxHint() { + String hintName = "openjpa.jdbc.JoinSyntax"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + joinSyntaxHintTest(fPlan, fConfig, hintName, String + .valueOf(JoinSyntaxes.SYNTAX_SQL92), JoinSyntax.SQL92, + JoinSyntaxes.SYNTAX_SQL92); + joinSyntaxHintTest(fPlan, fConfig, hintName, JoinSyntaxes.SYNTAX_SQL92, + JoinSyntax.SQL92, JoinSyntaxes.SYNTAX_SQL92); + + joinSyntaxHintTest(fPlan, fConfig, hintName, String + .valueOf(JoinSyntaxes.SYNTAX_TRADITIONAL), JoinSyntax.TRADITIONAL, + JoinSyntaxes.SYNTAX_TRADITIONAL); + joinSyntaxHintTest(fPlan, fConfig, hintName, + JoinSyntaxes.SYNTAX_TRADITIONAL, JoinSyntax.TRADITIONAL, + JoinSyntaxes.SYNTAX_TRADITIONAL); + + joinSyntaxHintTest(fPlan, fConfig, hintName, String + .valueOf(JoinSyntaxes.SYNTAX_DATABASE), JoinSyntax.DATABASE, + JoinSyntaxes.SYNTAX_DATABASE); + joinSyntaxHintTest(fPlan, fConfig, hintName, + JoinSyntaxes.SYNTAX_DATABASE, JoinSyntax.DATABASE, + JoinSyntaxes.SYNTAX_DATABASE); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(fConfig.getJoinSyntax(), + ((JDBCConfiguration) fConfig.getContext().getConfiguration()) + .getDBDictionaryInstance().joinSyntax); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void joinSyntaxHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getJoinSyntax()); + assertEquals(expected, fConfig.getJoinSyntax()); + } + + /* Good + * Test "openjpa.FetchPlan.FetchDirection" hint + */ + public void testFetchPlanFetchDirectionHint() { + String hintName = "openjpa.FetchPlan.FetchDirection"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + fetchDirectionHintTest(fPlan, fConfig, hintName, "forward", + FetchDirection.FORWARD, ResultSet.FETCH_FORWARD); + fetchDirectionHintTest(fPlan, fConfig, hintName, FetchDirection.FORWARD + .name(), FetchDirection.FORWARD, ResultSet.FETCH_FORWARD); + fetchDirectionHintTest(fPlan, fConfig, hintName, + FetchDirection.FORWARD, FetchDirection.FORWARD, + ResultSet.FETCH_FORWARD); + + fetchDirectionHintTest(fPlan, fConfig, hintName, "reverse", + FetchDirection.REVERSE, ResultSet.FETCH_REVERSE); + fetchDirectionHintTest(fPlan, fConfig, hintName, FetchDirection.REVERSE + .name(), FetchDirection.REVERSE, ResultSet.FETCH_REVERSE); + fetchDirectionHintTest(fPlan, fConfig, hintName, + FetchDirection.REVERSE, FetchDirection.REVERSE, + ResultSet.FETCH_REVERSE); + + fetchDirectionHintTest(fPlan, fConfig, hintName, "unknown", + FetchDirection.UNKNOWN, ResultSet.FETCH_UNKNOWN); + fetchDirectionHintTest(fPlan, fConfig, hintName, FetchDirection.UNKNOWN + .name(), FetchDirection.UNKNOWN, ResultSet.FETCH_UNKNOWN); + fetchDirectionHintTest(fPlan, fConfig, hintName, + FetchDirection.UNKNOWN, FetchDirection.UNKNOWN, + ResultSet.FETCH_UNKNOWN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.FetchDirection" hint + */ + public void testJdbcFetchDirectionHint() { + String hintName = "openjpa.jdbc.FetchDirection"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + fetchDirectionHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.FETCH_FORWARD), FetchDirection.FORWARD, + ResultSet.FETCH_FORWARD); + fetchDirectionHintTest(fPlan, fConfig, hintName, + ResultSet.FETCH_FORWARD, FetchDirection.FORWARD, + ResultSet.FETCH_FORWARD); + + fetchDirectionHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.FETCH_REVERSE), FetchDirection.REVERSE, + ResultSet.FETCH_REVERSE); + fetchDirectionHintTest(fPlan, fConfig, hintName, + ResultSet.FETCH_REVERSE, FetchDirection.REVERSE, + ResultSet.FETCH_REVERSE); + + fetchDirectionHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.FETCH_UNKNOWN), FetchDirection.UNKNOWN, + ResultSet.FETCH_UNKNOWN); + fetchDirectionHintTest(fPlan, fConfig, hintName, + ResultSet.FETCH_UNKNOWN, FetchDirection.UNKNOWN, + ResultSet.FETCH_UNKNOWN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(fConfig.getFetchDirection(), ResultSet.FETCH_FORWARD); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void fetchDirectionHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getFetchDirection()); + assertEquals(expected, fConfig.getFetchDirection()); + } + + /* Good + * Test "openjpa.FetchPlan.Isolation" hint + */ + public void testFetchPlanIsolationHint() { + String hintName = "openjpa.FetchPlan.Isolation"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + isolationHintTest(oem, fPlan, fConfig, hintName, "default", + IsolationLevel.DEFAULT, -1); + isolationHintTest(oem, fPlan, fConfig, hintName, "DEFAULT", + IsolationLevel.DEFAULT, -1); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.DEFAULT, IsolationLevel.DEFAULT, -1); + + boolean supportIsolationForUpdate = ((JDBCConfiguration) fConfig + .getContext().getConfiguration()).getDBDictionaryInstance() + .supportsIsolationForUpdate(); + if (supportIsolationForUpdate) { + isolationHintTest(oem, fPlan, fConfig, hintName, "none", + IsolationLevel.NONE, Connection.TRANSACTION_NONE); + isolationHintTest(oem, fPlan, fConfig, hintName, "NONE", + IsolationLevel.NONE, Connection.TRANSACTION_NONE); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.NONE, IsolationLevel.NONE, + Connection.TRANSACTION_NONE); + + isolationHintTest(oem, fPlan, fConfig, hintName, + "read-uncommitted", IsolationLevel.READ_UNCOMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, + "READ_UNCOMMITTED", IsolationLevel.READ_UNCOMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.READ_UNCOMMITTED, + IsolationLevel.READ_UNCOMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED); + + isolationHintTest(oem, fPlan, fConfig, hintName, "read-committed", + IsolationLevel.READ_COMMITTED, + Connection.TRANSACTION_READ_COMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, "READ_COMMITTED", + IsolationLevel.READ_COMMITTED, + Connection.TRANSACTION_READ_COMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.READ_COMMITTED, IsolationLevel.READ_COMMITTED, + Connection.TRANSACTION_READ_COMMITTED); + + isolationHintTest(oem, fPlan, fConfig, hintName, "repeatable-read", + IsolationLevel.REPEATABLE_READ, + Connection.TRANSACTION_REPEATABLE_READ); + isolationHintTest(oem, fPlan, fConfig, hintName, "REPEATABLE_READ", + IsolationLevel.REPEATABLE_READ, + Connection.TRANSACTION_REPEATABLE_READ); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.REPEATABLE_READ, IsolationLevel.REPEATABLE_READ, + Connection.TRANSACTION_REPEATABLE_READ); + + isolationHintTest(oem, fPlan, fConfig, hintName, "serializable", + IsolationLevel.SERIALIZABLE, + Connection.TRANSACTION_SERIALIZABLE); + isolationHintTest(oem, fPlan, fConfig, hintName, "SERIALIZABLE", + IsolationLevel.SERIALIZABLE, + Connection.TRANSACTION_SERIALIZABLE); + isolationHintTest(oem, fPlan, fConfig, hintName, + IsolationLevel.SERIALIZABLE, IsolationLevel.SERIALIZABLE, + Connection.TRANSACTION_SERIALIZABLE); + } + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -1, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.TransactionIsolation" hint + */ + public void testJdbcTransactionIsolationHint() { + String hintName = "openjpa.jdbc.TransactionIsolation"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + isolationHintTest(oem, fPlan, fConfig, hintName, "-1", + IsolationLevel.DEFAULT, -1); + isolationHintTest(oem, fPlan, fConfig, hintName, -1, + IsolationLevel.DEFAULT, -1); + + boolean supportIsolationForUpdate = ((JDBCConfiguration) fConfig + .getContext().getConfiguration()).getDBDictionaryInstance() + .supportsIsolationForUpdate(); + if (supportIsolationForUpdate) { + isolationHintTest(oem, fPlan, fConfig, hintName, String + .valueOf(Connection.TRANSACTION_NONE), IsolationLevel.NONE, + Connection.TRANSACTION_NONE); + isolationHintTest(oem, fPlan, fConfig, hintName, + Connection.TRANSACTION_NONE, IsolationLevel.NONE, + Connection.TRANSACTION_NONE); + + isolationHintTest(oem, fPlan, fConfig, hintName, String + .valueOf(Connection.TRANSACTION_READ_UNCOMMITTED), + IsolationLevel.READ_UNCOMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, + Connection.TRANSACTION_READ_UNCOMMITTED, + IsolationLevel.READ_UNCOMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED); + + isolationHintTest(oem, fPlan, fConfig, hintName, String + .valueOf(Connection.TRANSACTION_READ_COMMITTED), + IsolationLevel.READ_COMMITTED, + Connection.TRANSACTION_READ_COMMITTED); + isolationHintTest(oem, fPlan, fConfig, hintName, + Connection.TRANSACTION_READ_COMMITTED, + IsolationLevel.READ_COMMITTED, + Connection.TRANSACTION_READ_COMMITTED); + + isolationHintTest(oem, fPlan, fConfig, hintName, String + .valueOf(Connection.TRANSACTION_REPEATABLE_READ), + IsolationLevel.REPEATABLE_READ, + Connection.TRANSACTION_REPEATABLE_READ); + isolationHintTest(oem, fPlan, fConfig, hintName, + Connection.TRANSACTION_REPEATABLE_READ, + IsolationLevel.REPEATABLE_READ, + Connection.TRANSACTION_REPEATABLE_READ); + + isolationHintTest(oem, fPlan, fConfig, hintName, String + .valueOf(Connection.TRANSACTION_SERIALIZABLE), + IsolationLevel.SERIALIZABLE, + Connection.TRANSACTION_SERIALIZABLE); + isolationHintTest(oem, fPlan, fConfig, hintName, + Connection.TRANSACTION_SERIALIZABLE, + IsolationLevel.SERIALIZABLE, + Connection.TRANSACTION_SERIALIZABLE); + } + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(IsolationLevel.DEFAULT, fPlan.getIsolation()); + assertEquals(-1, fConfig.getIsolation()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + @SuppressWarnings("deprecation") + private void isolationHintTest(OpenJPAEntityManager oem, + JDBCFetchPlan fPlan, JDBCFetchConfigurationImpl fConfig, String hint, + Object value, Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getIsolation()); + assertEquals(expected, fConfig.getIsolation()); + } + + /* Good + * Test "openjpa.FetchPlan.LRSSizeAlgorithm" hint + */ + public void testFetchPlanLRSSizeAlgorithmHint() { + String hintName = "openjpa.FetchPlan.LRSSizeAlgorithm"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lrsSizeHintTest(fPlan, fConfig, hintName, "query", + LRSSizeAlgorithm.QUERY, LRSSizes.SIZE_QUERY); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.QUERY.name(), + LRSSizeAlgorithm.QUERY, LRSSizes.SIZE_QUERY); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.QUERY, + LRSSizeAlgorithm.QUERY, LRSSizes.SIZE_QUERY); + + lrsSizeHintTest(fPlan, fConfig, hintName, "last", + LRSSizeAlgorithm.LAST, LRSSizes.SIZE_LAST); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.LAST.name(), + LRSSizeAlgorithm.LAST, LRSSizes.SIZE_LAST); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.LAST, + LRSSizeAlgorithm.LAST, LRSSizes.SIZE_LAST); + + lrsSizeHintTest(fPlan, fConfig, hintName, "unknown", + LRSSizeAlgorithm.UNKNOWN, LRSSizes.SIZE_UNKNOWN); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.UNKNOWN + .name(), LRSSizeAlgorithm.UNKNOWN, LRSSizes.SIZE_UNKNOWN); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizeAlgorithm.UNKNOWN, + LRSSizeAlgorithm.UNKNOWN, LRSSizes.SIZE_UNKNOWN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.FetchPlan.LRSSize" hint + */ + @SuppressWarnings("deprecation") + public void testFetchPlanLRSSizeHint() { + String hintName = "openjpa.FetchPlan.LRSSize"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_QUERY), LRSSizeAlgorithm.QUERY, + LRSSizes.SIZE_QUERY); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_QUERY, + LRSSizeAlgorithm.QUERY, LRSSizes.SIZE_QUERY); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_LAST), LRSSizeAlgorithm.LAST, + LRSSizes.SIZE_LAST); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_LAST, + LRSSizeAlgorithm.LAST, LRSSizes.SIZE_LAST); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_UNKNOWN), LRSSizeAlgorithm.UNKNOWN, + LRSSizes.SIZE_UNKNOWN); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_UNKNOWN, + LRSSizeAlgorithm.UNKNOWN, LRSSizes.SIZE_UNKNOWN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(LRSSizeAlgorithm.QUERY, fPlan.getLRSSizeAlgorithm()); + assertEquals(LRSSizes.SIZE_QUERY, fPlan.getLRSSize()); + assertEquals(LRSSizes.SIZE_QUERY, fConfig.getLRSSize()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.LRSSize" hint + */ + @SuppressWarnings("deprecation") + public void testJdbcLRSSizeHint() { + String hintName = "openjpa.jdbc.LRSSize"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_QUERY), LRSSizeAlgorithm.QUERY, + LRSSizes.SIZE_QUERY); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_QUERY, + LRSSizeAlgorithm.QUERY, LRSSizes.SIZE_QUERY); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_LAST), LRSSizeAlgorithm.LAST, + LRSSizes.SIZE_LAST); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_LAST, + LRSSizeAlgorithm.LAST, LRSSizes.SIZE_LAST); + + lrsSizeHintTest(fPlan, fConfig, hintName, String + .valueOf(LRSSizes.SIZE_UNKNOWN), LRSSizeAlgorithm.UNKNOWN, + LRSSizes.SIZE_UNKNOWN); + lrsSizeHintTest(fPlan, fConfig, hintName, LRSSizes.SIZE_UNKNOWN, + LRSSizeAlgorithm.UNKNOWN, LRSSizes.SIZE_UNKNOWN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(LRSSizeAlgorithm.QUERY, fPlan.getLRSSizeAlgorithm()); + assertEquals(LRSSizes.SIZE_QUERY, fPlan.getLRSSize()); + assertEquals(LRSSizes.SIZE_QUERY, fConfig.getLRSSize()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + @SuppressWarnings("deprecation") + private void lrsSizeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getLRSSizeAlgorithm()); + assertEquals(expected, fPlan.getLRSSize()); + assertEquals(expected, fConfig.getLRSSize()); + } + + /* Good + * Test "openjpa.FetchPlan.MaxFetchDepth" hint + */ + public void testFetchPlanMaxFetchDepthHint() { + String hintName = "openjpa.FetchPlan.MaxFetchDepth"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + maxFetchDepthHintTest(fPlan, fConfig, hintName, "-1", -1); + maxFetchDepthHintTest(fPlan, fConfig, hintName, -1, -1); + maxFetchDepthHintTest(fPlan, fConfig, hintName, "500", 500); + maxFetchDepthHintTest(fPlan, fConfig, hintName, 500, 500); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(-1, fPlan.getMaxFetchDepth()); + assertEquals(-1, fConfig.getMaxFetchDepth()); + } catch (IllegalArgumentException e) { + fail("Unexpected IllegalArgumentException."); + } + em.close(); + } + + /* Good + * Test "openjpa.MaxFetchDepth" hint + */ + public void testMaxFetchDepthHint() { + String hintName = "openjpa.MaxFetchDepth"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + maxFetchDepthHintTest(fPlan, fConfig, hintName, "-1", -1); + maxFetchDepthHintTest(fPlan, fConfig, hintName, -1, -1); + maxFetchDepthHintTest(fPlan, fConfig, hintName, "100", 100); + maxFetchDepthHintTest(fPlan, fConfig, hintName, 100, 100); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(-1, fPlan.getMaxFetchDepth()); + assertEquals(-1, fConfig.getMaxFetchDepth()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void maxFetchDepthHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expected, fPlan.getMaxFetchDepth()); + assertEquals(expected, fConfig.getMaxFetchDepth()); + } + + /* Good + * Test "openjpa.LockTimeout" hint + */ + public void testLockTimeoutHint() { + String hintName = "openjpa.LockTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lockTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, "100", 100); + lockTimeoutHintTest(fPlan, fConfig, hintName, 100, 100); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getLockTimeout(); + assertEquals(defTimeout, fPlan.getLockTimeout()); + assertEquals(defTimeout, fConfig.getLockTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "openjpa.FetchPlan.LockTimeout" hint + */ + public void testFetchPlanLockTimeoutHint() { + String hintName = "openjpa.FetchPlan.LockTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lockTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, "1500", 1500); + lockTimeoutHintTest(fPlan, fConfig, hintName, 1500, 1500); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getLockTimeout(); + assertEquals(defTimeout, fPlan.getLockTimeout()); + assertEquals(defTimeout, fConfig.getLockTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "javax.persistence.lock.timeout" hint + */ + public void testJavaxLockTimeoutHint() { + String hintName = "javax.persistence.lock.timeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + lockTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + lockTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + lockTimeoutHintTest(fPlan, fConfig, hintName, "2000", 2000); + lockTimeoutHintTest(fPlan, fConfig, hintName, 2000, 2000); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getLockTimeout(); + assertEquals(defTimeout, fPlan.getLockTimeout()); + assertEquals(defTimeout, fConfig.getLockTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void lockTimeoutHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expected, fPlan.getLockTimeout()); + assertEquals(expected, fConfig.getLockTimeout()); + } + + /* Good + * Test "openjpa.QueryTimeout" hint + */ + public void testQueryTimeoutHint() { + String hintName = "openjpa.QueryTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + queryTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, "100", 100); + queryTimeoutHintTest(fPlan, fConfig, hintName, 100, 100); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getQueryTimeout(); + assertEquals(defTimeout, fPlan.getQueryTimeout()); + assertEquals(defTimeout, fConfig.getQueryTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "openjpa.FetchPlan.QueryTimeout" hint + */ + public void testFetchPlanQueryTimeoutHint() { + String hintName = "openjpa.FetchPlan.QueryTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + queryTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, "1500", 1500); + queryTimeoutHintTest(fPlan, fConfig, hintName, 1500, 1500); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getQueryTimeout(); + assertEquals(defTimeout, fPlan.getQueryTimeout()); + assertEquals(defTimeout, fConfig.getQueryTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + /* Good + * Test "javax.persistence.query.timeout" hint + */ + public void testJavaxQueryTimeoutHint() { + String hintName = "javax.persistence.query.timeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + queryTimeoutHintTest(fPlan, fConfig, hintName, "-1", -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, -1, -1); + queryTimeoutHintTest(fPlan, fConfig, hintName, "0", 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, 0, 0); + queryTimeoutHintTest(fPlan, fConfig, hintName, "2000", 2000); + queryTimeoutHintTest(fPlan, fConfig, hintName, 2000, 2000); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -2, false); + fPlan.setHint(hintName, -3, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + int defTimeout = fConfig.getContext().getConfiguration() + .getQueryTimeout(); + assertEquals(defTimeout, fPlan.getQueryTimeout()); + assertEquals(defTimeout, fConfig.getQueryTimeout()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void queryTimeoutHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expected, fPlan.getQueryTimeout()); + assertEquals(expected, fConfig.getQueryTimeout()); + } + + /* Good + * Test "openjpa.FetchPlan.ResultSetType" hint + */ + public void testFetchPlanResultSetTypeHint() { + String hintName = "openjpa.FetchPlan.ResultSetType"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.FORWARD_ONLY.name(), ResultSetType.FORWARD_ONLY, + ResultSet.TYPE_FORWARD_ONLY); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.FORWARD_ONLY, ResultSetType.FORWARD_ONLY, + ResultSet.TYPE_FORWARD_ONLY); + + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.SCROLL_SENSITIVE.name(), + ResultSetType.SCROLL_SENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.SCROLL_SENSITIVE, ResultSetType.SCROLL_SENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE); + + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.SCROLL_INSENSITIVE.name(), + ResultSetType.SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_INSENSITIVE); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSetType.SCROLL_INSENSITIVE, ResultSetType.SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_INSENSITIVE); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.ResultSetType" hint + */ + public void testJdbcResultSetTypeHint() { + String hintName = "openjpa.jdbc.ResultSetType"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + resultSetTypeHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.TYPE_FORWARD_ONLY), ResultSetType.FORWARD_ONLY, + ResultSet.TYPE_FORWARD_ONLY); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSet.TYPE_FORWARD_ONLY, ResultSetType.FORWARD_ONLY, + ResultSet.TYPE_FORWARD_ONLY); + + resultSetTypeHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.TYPE_SCROLL_SENSITIVE), + ResultSetType.SCROLL_SENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSetType.SCROLL_SENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE); + + resultSetTypeHintTest(fPlan, fConfig, hintName, String + .valueOf(ResultSet.TYPE_SCROLL_INSENSITIVE), + ResultSetType.SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_INSENSITIVE); + resultSetTypeHintTest(fPlan, fConfig, hintName, + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSetType.SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_INSENSITIVE); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(ResultSet.TYPE_FORWARD_ONLY, fConfig + .getResultSetType()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void resultSetTypeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getResultSetType()); + assertEquals(expected, fConfig.getResultSetType()); + } + + /* Good + * Test "openjpa.FetchPlan.SubclassFetchMode" hint + */ + public void testFetchPlanSubclassFetchModeHint() { + String hintName = "openjpa.FetchPlan.SubclassFetchMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, "none", + FetchMode.NONE, EagerFetchModes.EAGER_NONE); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.NONE + .name(), FetchMode.NONE, EagerFetchModes.EAGER_NONE); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.NONE, + FetchMode.NONE, EagerFetchModes.EAGER_NONE); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, "parallel", + FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.PARALLEL + .name(), FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.PARALLEL, + FetchMode.PARALLEL, EagerFetchModes.EAGER_PARALLEL); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, "join", + FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.JOIN + .name(), FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + subclassFetchModeHintTest(fPlan, fConfig, hintName, FetchMode.JOIN, + FetchMode.JOIN, EagerFetchModes.EAGER_JOIN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* Good + * Test "openjpa.jdbc.SubclassFetchMode" hint + */ + public void testJdbcSubclassFetchModeHint() { + String hintName = "openjpa.jdbc.SubclassFetchMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_NONE), FetchMode.NONE, + EagerFetchModes.EAGER_NONE); + subclassFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_NONE, FetchMode.NONE, + EagerFetchModes.EAGER_NONE); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_PARALLEL), FetchMode.PARALLEL, + EagerFetchModes.EAGER_PARALLEL); + subclassFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_PARALLEL, FetchMode.PARALLEL, + EagerFetchModes.EAGER_PARALLEL); + + subclassFetchModeHintTest(fPlan, fConfig, hintName, String + .valueOf(EagerFetchModes.EAGER_JOIN), FetchMode.JOIN, + EagerFetchModes.EAGER_JOIN); + subclassFetchModeHintTest(fPlan, fConfig, hintName, + EagerFetchModes.EAGER_JOIN, FetchMode.JOIN, + EagerFetchModes.EAGER_JOIN); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(EagerFetchModes.EAGER_JOIN, fConfig + .getSubclassFetchMode()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void subclassFetchModeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedValue, int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedValue, fPlan.getSubclassFetchMode()); + assertEquals(expected, fConfig.getSubclassFetchMode()); + } + + /* Good + * Test "openjpa.FlushBeforeQueries" hint + */ + public void testFlushBeforeQueriesHint() { + String hintName = "openjpa.FlushBeforeQueries"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, String + .valueOf(QueryFlushModes.FLUSH_TRUE), QueryFlushModes.FLUSH_TRUE); + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, + QueryFlushModes.FLUSH_TRUE, QueryFlushModes.FLUSH_TRUE); + + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, String + .valueOf(QueryFlushModes.FLUSH_FALSE), QueryFlushModes.FLUSH_FALSE); + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, + QueryFlushModes.FLUSH_FALSE, QueryFlushModes.FLUSH_FALSE); + + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, String + .valueOf(QueryFlushModes.FLUSH_WITH_CONNECTION), + QueryFlushModes.FLUSH_WITH_CONNECTION); + flushBeforeQueriesHintTest(fPlan, fConfig, hintName, + QueryFlushModes.FLUSH_WITH_CONNECTION, + QueryFlushModes.FLUSH_WITH_CONNECTION); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + fConfig.getFlushBeforeQueries(); + assertEquals(QueryFlushModes.FLUSH_TRUE, fConfig + .getFlushBeforeQueries()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.close(); + } + + private void flushBeforeQueriesHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + int expected) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expected, fConfig.getFlushBeforeQueries()); + } + + /* Good + * Test "openjpa.ReadLockLevel" hint + */ + public void testReadLockLevelHint() { + String hintName = "openjpa.ReadLockLevel"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + em.getTransaction().begin(); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_NONE), LockModeType.NONE, + MixedLockLevels.LOCK_NONE); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_NONE, LockModeType.NONE, + MixedLockLevels.LOCK_NONE); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_READ), LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_READ); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_READ, LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_READ); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_WRITE), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_WRITE, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_OPTIMISTIC), LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + readLockLevelHintTest(fPlan, fConfig, hintName, 10, + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + + readLockLevelHintTest(fPlan, fConfig, hintName, + String.valueOf(MixedLockLevels.LOCK_PESSIMISTIC_READ), + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_READ, + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + + readLockLevelHintTest(fPlan, fConfig, hintName, + String.valueOf(MixedLockLevels.LOCK_PESSIMISTIC_WRITE), + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE, + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + + readLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT), + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + readLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(MixedLockLevels.LOCK_READ, fConfig.getReadLockLevel()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.getTransaction().rollback(); + em.close(); + } + + private void readLockLevelHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedMode, int expectedLevel) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedMode, fPlan.getReadLockMode()); + assertEquals(expectedLevel, fConfig.getReadLockLevel()); + } + + /* Good + * Test "openjpa.WriteLockLevel" hint + */ + public void testWriteLockLevelHint() { + String hintName = "openjpa.WriteLockLevel"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + em.getTransaction().begin(); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_NONE), LockModeType.NONE, + MixedLockLevels.LOCK_NONE); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_NONE, LockModeType.NONE, + MixedLockLevels.LOCK_NONE); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_READ), LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_READ); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_READ, LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_READ); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_WRITE), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_WRITE, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_OPTIMISTIC), LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_OPTIMISTIC, LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + + writeLockLevelHintTest(fPlan, fConfig, hintName, + String.valueOf(MixedLockLevels.LOCK_PESSIMISTIC_READ), + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_READ, + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + + writeLockLevelHintTest(fPlan, fConfig, hintName, + String.valueOf(MixedLockLevels.LOCK_PESSIMISTIC_WRITE), + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE, + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + + writeLockLevelHintTest(fPlan, fConfig, hintName, String + .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT), + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + writeLockLevelHintTest(fPlan, fConfig, hintName, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, FetchConfiguration.DEFAULT, true); + assertEquals(MixedLockLevels.LOCK_WRITE, fConfig + .getWriteLockLevel()); + } catch (Exception e) { + fail("Unexpected " + e.getClass().getName()); + } + em.getTransaction().rollback(); + em.close(); + } + + private void writeLockLevelHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedMode, int expectedLevel) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedMode, fPlan.getWriteLockMode()); + assertEquals(expectedLevel, fConfig.getWriteLockLevel()); + } + + /* Good + * Test "openjpa.FetchPlan.ReadLockMode" hint + */ + public void testFetchPlanReadLockModeHintInTx() { + fetchPlanReadLockModeHint(true); + } + + public void testFetchPlanReadLockModeHintNotInTx() { + fetchPlanReadLockModeHint(false); + } + + private void fetchPlanReadLockModeHint(boolean inTransaction) { + String hintName = "openjpa.FetchPlan.ReadLockMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + if(inTransaction) + em.getTransaction().begin(); + + readLockModeHintTest(fPlan, fConfig, hintName, "none", + LockModeType.NONE, MixedLockLevels.LOCK_NONE); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.NONE, + LockModeType.NONE, MixedLockLevels.LOCK_NONE); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.NONE.name(), LockModeType.NONE, + MixedLockLevels.LOCK_NONE); + + readLockModeHintTest(fPlan, fConfig, hintName, "read", + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.READ, + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.READ.name(), LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + + readLockModeHintTest(fPlan, fConfig, hintName, "write", + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.WRITE, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.WRITE + .name(), LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + + readLockModeHintTest(fPlan, fConfig, hintName, "optimistic", + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.OPTIMISTIC, + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + readLockModeHintTest(fPlan, fConfig, hintName, LockModeType.OPTIMISTIC + .name(), LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + + readLockModeHintTest(fPlan, fConfig, hintName, + "optimistic-force-increment", + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.OPTIMISTIC_FORCE_INCREMENT.name(), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + + readLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-read", LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_READ, LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_READ.name(), + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + + readLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-write", LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_WRITE, LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_WRITE.name(), + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + + readLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-force-increment", + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + readLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_FORCE_INCREMENT.name(), + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + if(inTransaction) + em.getTransaction().rollback(); + em.close(); + } + + private void readLockModeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedMode, int expectedLevel) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedMode, fPlan.getReadLockMode()); + assertEquals(expectedLevel, fConfig.getReadLockLevel()); + } + + /* Good + * Test "openjpa.FetchPlan.WriteLockMode" hint + */ + public void testFetchPlanWriteLockModeHintInTx() { + fetchPlanWriteLockModeHint(true); + } + + public void testFetchPlanWriteLockModeHintNotInTx() { + fetchPlanWriteLockModeHint(false); + } + + private void fetchPlanWriteLockModeHint(boolean inTransaction) { + String hintName = "openjpa.FetchPlan.WriteLockMode"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + if(inTransaction) + em.getTransaction().begin(); + + writeLockModeHintTest(fPlan, fConfig, hintName, "none", + LockModeType.NONE, MixedLockLevels.LOCK_NONE); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.NONE, + LockModeType.NONE, MixedLockLevels.LOCK_NONE); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.NONE + .name(), LockModeType.NONE, MixedLockLevels.LOCK_NONE); + + writeLockModeHintTest(fPlan, fConfig, hintName, "read", + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_READ); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.READ, + LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_READ); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.READ + .name(), LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_READ); + + writeLockModeHintTest(fPlan, fConfig, hintName, "write", + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.WRITE, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.WRITE + .name(), LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_WRITE); + + writeLockModeHintTest(fPlan, fConfig, hintName, + "optimistic", LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.OPTIMISTIC, LockModeType.OPTIMISTIC, + MixedLockLevels.LOCK_OPTIMISTIC); + writeLockModeHintTest(fPlan, fConfig, hintName, LockModeType.OPTIMISTIC + .name(), LockModeType.OPTIMISTIC, MixedLockLevels.LOCK_OPTIMISTIC); + + writeLockModeHintTest(fPlan, fConfig, hintName, + "optimistic-force-increment", + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.OPTIMISTIC_FORCE_INCREMENT.name(), + LockModeType.OPTIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT); + + writeLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-read", LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_READ, LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_READ.name(), + LockModeType.PESSIMISTIC_READ, + MixedLockLevels.LOCK_PESSIMISTIC_READ); + + writeLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-write", LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_WRITE, LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_WRITE.name(), + LockModeType.PESSIMISTIC_WRITE, + MixedLockLevels.LOCK_PESSIMISTIC_WRITE); + + writeLockModeHintTest(fPlan, fConfig, hintName, + "pessimistic-force-increment", + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + writeLockModeHintTest(fPlan, fConfig, hintName, + LockModeType.PESSIMISTIC_FORCE_INCREMENT.name(), + LockModeType.PESSIMISTIC_FORCE_INCREMENT, + MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT); + + try { + fPlan.setHint(hintName, "xxxxx", false); + fPlan.setHint(hintName, "yyyyy", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, "12345", false); + fPlan.setHint(hintName, "67890", true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + try { + fPlan.setHint(hintName, -1, false); + fPlan.setHint(hintName, -2, true); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + if(inTransaction) + em.getTransaction().rollback(); + em.close(); + } + + private void writeLockModeHintTest(JDBCFetchPlan fPlan, + JDBCFetchConfigurationImpl fConfig, String hint, Object value, + Object expectedMode, Object expectedLevel) { + fPlan.setHint(hint, value); + Object getValue = fPlan.getHint(hint); + assertEquals(value.getClass(), getValue.getClass()); + assertEquals(value, getValue); + assertEquals(expectedMode, fPlan.getWriteLockMode()); + assertEquals(expectedLevel, fConfig.getWriteLockLevel()); + } + + /* Good + * Test precendence order of similiar/equivalent LockTimeout hints. + */ + public void testSimiliarLockTimeoutHints() { + String JavaxLockTimeout = "javax.persistence.lock.timeout"; + String OpenJPALockTimeout = "openjpa.LockTimeout"; + String FetchPlanLockTimeout = "openjpa.FetchPlan.LockTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + + similarLockTimeoutHintsTest(oem, 333, + JavaxLockTimeout, 333, + OpenJPALockTimeout, 111, + FetchPlanLockTimeout, 222); + similarLockTimeoutHintsTest(oem, 333, + OpenJPALockTimeout, 111, + FetchPlanLockTimeout, 222, + JavaxLockTimeout, 333); + similarLockTimeoutHintsTest(oem, 333, + JavaxLockTimeout, 333, + FetchPlanLockTimeout, 222, + OpenJPALockTimeout, 111); + similarLockTimeoutHintsTest(oem, 222, + OpenJPALockTimeout, 111, + FetchPlanLockTimeout, 222); + similarLockTimeoutHintsTest(oem, 222, + FetchPlanLockTimeout, 222, + OpenJPALockTimeout, 111); + similarLockTimeoutHintsTest(oem, 111, + OpenJPALockTimeout, 111); + similarLockTimeoutHintsTest(oem, 222, + FetchPlanLockTimeout, 222); + similarLockTimeoutHintsTest(oem, 333, + JavaxLockTimeout, 333); + + em.close(); + } + + @SuppressWarnings("deprecation") + private void similarLockTimeoutHintsTest(OpenJPAEntityManager oem, + Object expected, Object... hintNvalues) { + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.pushFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) fPlan + .getDelegate(); + + for( int i = 0 ; i < hintNvalues.length ; i += 2) { + fPlan.setHint((String)hintNvalues[i], hintNvalues[i+1]); + } + for( int i = 0 ; i < hintNvalues.length ; i += 2) { + String hintName = (String)hintNvalues[i]; + Object expectedValue = hintNvalues[i+1]; + Object getValue = fPlan.getHint(hintName); + assertEquals(expectedValue.getClass(), getValue.getClass()); + assertEquals(expectedValue, getValue); + } + assertEquals(expected, fPlan.getLockTimeout()); + assertEquals(expected, fConfig.getLockTimeout()); + + oem.popFetchPlan(); + } + + /* Good + * Test precendence order of similiar/equivalent QueryTimeout hints. + */ + public void testSimiliarQueryTimeoutHints() { + String JavaxQueryTimeout = "javax.persistence.query.timeout"; + String OpenJPAQueryTimeout = "openjpa.QueryTimeout"; + String FetchPlanQueryTimeout = "openjpa.FetchPlan.QueryTimeout"; + + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + + similarQueryTimeoutHintsTest(oem, 333, + JavaxQueryTimeout, 333, + OpenJPAQueryTimeout, 111, + FetchPlanQueryTimeout, 222); + similarQueryTimeoutHintsTest(oem, 333, + OpenJPAQueryTimeout, 111, + FetchPlanQueryTimeout, 222, + JavaxQueryTimeout, 333); + similarQueryTimeoutHintsTest(oem, 333, + JavaxQueryTimeout, 333, + FetchPlanQueryTimeout, 222, + OpenJPAQueryTimeout, 111); + similarQueryTimeoutHintsTest(oem, 222, + OpenJPAQueryTimeout, 111, + FetchPlanQueryTimeout, 222); + similarQueryTimeoutHintsTest(oem, 222, + FetchPlanQueryTimeout, 222, + OpenJPAQueryTimeout, 111); + similarQueryTimeoutHintsTest(oem, 111, + OpenJPAQueryTimeout, 111); + similarQueryTimeoutHintsTest(oem, 222, + FetchPlanQueryTimeout, 222); + similarQueryTimeoutHintsTest(oem, 333, + JavaxQueryTimeout, 333); + + em.close(); + } + + @SuppressWarnings("deprecation") + private void similarQueryTimeoutHintsTest(OpenJPAEntityManager oem, + Object expected, Object... hintNvalues) { + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.pushFetchPlan(); + JDBCFetchConfigurationImpl fConfig = (JDBCFetchConfigurationImpl) fPlan + .getDelegate(); + + for( int i = 0 ; i < hintNvalues.length ; i += 2) { + fPlan.setHint((String)hintNvalues[i], hintNvalues[i+1]); + } + for( int i = 0 ; i < hintNvalues.length ; i += 2) { + String hintName = (String)hintNvalues[i]; + Object expectedValue = hintNvalues[i+1]; + Object getValue = fPlan.getHint(hintName); + assertEquals(expectedValue.getClass(), getValue.getClass()); + assertEquals(expectedValue, getValue); + } + assertEquals(expected, fPlan.getQueryTimeout()); + assertEquals(expected, fConfig.getQueryTimeout()); + + oem.popFetchPlan(); + } + + /* + * Test various forms setHint argument. + */ + @SuppressWarnings("deprecation") + public void testSetHintAddHintsArgument() { + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + JDBCFetchPlan fPlan = (JDBCFetchPlan) oem.getFetchPlan(); + + fPlan.setHint("unrecognized.prop.name", "unrecognized.prop.value"); + assertEquals(null, fPlan.getHint("unrecognized.prop.name")); + + fPlan.addHints(null); + fPlan.addHints(new HashMap()); + + OpenJPAConfiguration conf = oem.getConfiguration(); + if (conf instanceof JDBCConfiguration + && ((JDBCConfiguration) conf).getDBDictionaryInstance() + .supportsIsolationForUpdate()) { + try { + fPlan.setHint("openjpa.jdbc.TransactionIsolation", 9999); + fail("Expecting a a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e + .getClass())); + } + } + + try { + fPlan.setHint("openjpa.FetchPlan.Isolation", new Integer(13), + false); + fPlan.setHint("openjpa.FetchPlan.Isolation", new Integer(14), + true); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } + + /* + * Test invalid hint via Query interface. + */ + public void testInvalidQuerySetHint() { + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager oem = (OpenJPAEntityManager)em.getDelegate(); + ((EntityManagerImpl) oem).getBroker().getFetchConfiguration(); + + Query q = em.createQuery("select o from LockEmployee o"); + try { + q.setHint("openjpa.FetchPlan.Isolation", "yyyyy"); + fail("Expecting a IllegalArgumentException."); + } catch (Exception e) { + assertTrue("Caught expected exception", + IllegalArgumentException.class.isAssignableFrom(e.getClass())); + } + em.close(); + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindBasicTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindBasic.java similarity index 98% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindBasicTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindBasic.java index 74c8b1c95..bfc04d356 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindBasicTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindBasic.java @@ -23,7 +23,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 em.find(LockMode) behaviors with "mixed" lock manager. */ -public class MixedLockManagerFindBasicTest extends SequencedActionsTest { +public class TestMixedLockManagerFindBasic extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindExceptionTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindException.java similarity index 99% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindExceptionTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindException.java index 649610d31..0a5dec0e1 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindExceptionTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindException.java @@ -26,7 +26,7 @@ import javax.persistence.TransactionRequiredException; /** * Test JPA 2.0 em.find(LockMode) exception behaviors with "mixed" lock manager. */ -public class MixedLockManagerFindExceptionTest extends SequencedActionsTest { +public class TestMixedLockManagerFindException extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindPermutationTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindPermutation.java similarity index 99% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindPermutationTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindPermutation.java index 42f43b066..245b6ad94 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerFindPermutationTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerFindPermutation.java @@ -25,7 +25,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 LockMode type permutation behaviors with "mixed" lock manager. */ -public class MixedLockManagerFindPermutationTest extends SequencedActionsTest { +public class TestMixedLockManagerFindPermutation extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockBasicTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockBasic.java similarity index 98% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockBasicTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockBasic.java index a1e7d78e2..b43fca6f7 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockBasicTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockBasic.java @@ -23,7 +23,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 em.lock(LockMode) basic behaviors with "mixed" lock manager. */ -public class MixedLockManagerLockBasicTest extends SequencedActionsTest { +public class TestMixedLockManagerLockBasic extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockExceptionTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockException.java similarity index 99% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockExceptionTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockException.java index 07ad16b6a..87da460c5 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockExceptionTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockException.java @@ -25,7 +25,7 @@ import javax.persistence.TransactionRequiredException; /** * Test JPA 2.0 em.lock(LockMode) exception behaviors with "mixed" lock manager. */ -public class MixedLockManagerLockExceptionTest extends SequencedActionsTest { +public class TestMixedLockManagerLockException extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockPermutationTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockPermutation.java similarity index 99% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockPermutationTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockPermutation.java index 8d6d7f0a9..61df7419d 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerLockPermutationTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerLockPermutation.java @@ -25,7 +25,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 LockMode type permutation behaviors with "mixed" lock manager. */ -public class MixedLockManagerLockPermutationTest extends SequencedActionsTest { +public class TestMixedLockManagerLockPermutation extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshBasicTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshBasic.java similarity index 98% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshBasicTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshBasic.java index 2c7138b2c..040786872 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshBasicTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshBasic.java @@ -23,7 +23,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 em.refresh(LockMode) basic behaviors with "mixed" lock manager. */ -public class MixedLockManagerRefreshBasicTest extends SequencedActionsTest { +public class TestMixedLockManagerRefreshBasic extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshExceptionTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java similarity index 87% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshExceptionTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java index 833781d5a..96f393507 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshExceptionTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java @@ -25,7 +25,7 @@ import javax.persistence.TransactionRequiredException; * Test JPA 2.0 em.refresh(LockMode) exception behaviors with "mixed" * lock manager. */ -public class MixedLockManagerRefreshExceptionTest extends SequencedActionsTest { +public class TestMixedLockManagerRefreshException extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class , "openjpa.LockManager", "mixed" @@ -33,6 +33,44 @@ public class MixedLockManagerRefreshExceptionTest extends SequencedActionsTest { commonSetUp(); } + /** + * TransactionRequiredException if there is no transaction + */ + public void testRefreshNoTxReqExceptions() { + Object[][] threadMainTxReqTest = { + {Act.CreateEm}, + {Act.Find}, + {Act.SaveVersion}, + {Act.TestEmployee, 1, Default_FirstName}, + + {Act.Refresh, 1, LockModeType.NONE }, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.READ }, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.WRITE }, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.OPTIMISTIC }, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT }, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.PESSIMISTIC_READ}, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.PESSIMISTIC_WRITE}, + {Act.TestException, 0, null }, + + {Act.Refresh, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT }, + {Act.TestException, 0, null }, + }; + launchActionSequence("testLockTxReqExceptions()", + null, threadMainTxReqTest); + } + /** * TransactionRequiredException if there is no transaction */ @@ -43,28 +81,28 @@ public class MixedLockManagerRefreshExceptionTest extends SequencedActionsTest { {Act.SaveVersion}, {Act.TestEmployee, 1, Default_FirstName}, - {Act.Refresh, 1, LockModeType.NONE }, + {Act.RefreshWithLock, 1, LockModeType.NONE }, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.READ }, + {Act.RefreshWithLock, 1, LockModeType.READ }, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.WRITE }, + {Act.RefreshWithLock, 1, LockModeType.WRITE }, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.OPTIMISTIC }, + {Act.RefreshWithLock, 1, LockModeType.OPTIMISTIC }, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT }, + {Act.RefreshWithLock, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT }, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.PESSIMISTIC_READ}, + {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_READ}, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.PESSIMISTIC_WRITE}, + {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_WRITE}, {Act.TestException, 0, TransactionRequiredException.class }, - {Act.Refresh, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT }, + {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT }, {Act.TestException, 0, TransactionRequiredException.class }, }; launchActionSequence("testLockTxReqExceptions()", diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshPermutationTest.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java similarity index 99% rename from openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshPermutationTest.java rename to openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java index 54f3ad341..5e8f5fa18 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/MixedLockManagerRefreshPermutationTest.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java @@ -25,7 +25,7 @@ import javax.persistence.LockModeType; /** * Test JPA 2.0 LockMode type permutation behaviors with "mixed" lock manager. */ -public class MixedLockManagerRefreshPermutationTest +public class TestMixedLockManagerRefreshPermutation extends SequencedActionsTest { public void setUp() { setUp(LockEmployee.class diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java index 58ba1ce76..cca77bf6e 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java @@ -780,7 +780,7 @@ public class TestQueryTimeout extends SQLListenerTestCase { } catch (Exception e) { // expected - setHint(-2000) should cause an IllegalArgumentException checkException("testQueryTimeout5()", e, - IllegalArgumentException.class, "Invalid value" ); + IllegalArgumentException.class, "invalid timeout of -2,000"); } finally { if ((em != null) && em.isOpen()) { em.close(); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java index bebb6c1ec..a59eac71b 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java @@ -56,7 +56,6 @@ import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.DelegatingBroker; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.FindCallbacks; -import org.apache.openjpa.kernel.MixedLockLevels; import org.apache.openjpa.kernel.OpCallbacks; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PreparedQuery; @@ -65,16 +64,12 @@ import org.apache.openjpa.kernel.QueryFlushModes; import org.apache.openjpa.kernel.QueryLanguages; import org.apache.openjpa.kernel.Seq; import org.apache.openjpa.kernel.jpql.JPQLParser; -import org.apache.openjpa.lib.conf.Configuration; -import org.apache.openjpa.lib.conf.IntValue; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.QueryMetaData; import org.apache.openjpa.meta.SequenceMetaData; -import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder; -import org.apache.openjpa.persistence.query.QueryBuilderImpl; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.RuntimeExceptionTranslator; @@ -469,19 +464,24 @@ public class EntityManagerImpl return find(cls, oid, mode, null); } + public T find(Class cls, Object oid, + Map properties){ + return find(cls, oid, null, properties); + } + @SuppressWarnings("unchecked") public T find(Class cls, Object oid, LockModeType mode, Map properties) { assertNotCloseInvoked(); - if (mode != LockModeType.NONE) + if (mode != null && mode != LockModeType.NONE) _broker.assertActiveTransaction(); - boolean fcPushed = pushLockProperties(mode, properties); + processLockProperties(pushFetchPlan(), mode, properties); try { oid = _broker.newObjectId(cls, oid); return (T) _broker.find(oid, true, this); } finally { - popLockProperties(fcPushed); + popFetchPlan(); } } @@ -726,6 +726,10 @@ public class EntityManagerImpl refresh(entity, mode, null); } + public void refresh(Object entity, Map properties) { + refresh(entity, null, properties); + } + public void refresh(Object entity, LockModeType mode, Map properties) { assertNotCloseInvoked(); @@ -733,11 +737,11 @@ public class EntityManagerImpl _broker.assertActiveTransaction(); _broker.assertWriteOperation(); - boolean fcPushed = pushLockProperties(mode, properties); + processLockProperties(pushFetchPlan(), mode, properties); try { _broker.refresh(entity, this); } finally { - popLockProperties(fcPushed); + popFetchPlan(); } } @@ -1096,9 +1100,7 @@ public class EntityManagerImpl } public void lock(Object entity, LockModeType mode) { - assertNotCloseInvoked(); - assertValidAttchedEntity(entity); - _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), -1, this); + lock(entity, mode, -1); } public void lock(Object entity) { @@ -1110,8 +1112,14 @@ public class EntityManagerImpl public void lock(Object entity, LockModeType mode, int timeout) { assertNotCloseInvoked(); assertValidAttchedEntity(entity); - _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), timeout, - this); + + processLockProperties(pushFetchPlan(), mode, null); + try { + _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), + timeout, this); + } finally { + popFetchPlan(); + } } public void lock(Object entity, LockModeType mode, @@ -1120,12 +1128,12 @@ public class EntityManagerImpl assertValidAttchedEntity(entity); _broker.assertActiveTransaction(); - boolean fcPushed = pushLockProperties(mode, properties); + processLockProperties(pushFetchPlan(), mode, properties); try { _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), _broker.getFetchConfiguration().getLockTimeout(), this); } finally { - popLockProperties(fcPushed); + popFetchPlan(); } } @@ -1542,8 +1550,7 @@ public class EntityManagerImpl throw new PersistenceException(_loc.get("unwrap-em-invalid", cls) .toString(), null, this, false); } - - + public void setQuerySQLCache(boolean flag) { _broker.setCachePreparedQuery(flag); } @@ -1556,154 +1563,26 @@ public class EntityManagerImpl return _ret; } - private enum FetchConfigProperty { - LockTimeout, ReadLockLevel, WriteLockLevel - }; - - private boolean setFetchConfigProperty(FetchConfigProperty[] validProps, + private void processLockProperties(FetchPlan fPlan, LockModeType mode, Map properties) { - boolean fcPushed = false; - if (properties != null && properties.size() > 0) { - Configuration conf = _broker.getConfiguration(); - Set inKeys = properties.keySet(); - for (String inKey : inKeys) { - for (FetchConfigProperty validProp : validProps) { - String validPropStr = validProp.toString(); - Set validPropKeys = conf - .getPropertyKeys(validPropStr); - - if (validPropKeys.contains(inKey)) { - FetchConfiguration fCfg = _broker - .getFetchConfiguration(); - IntValue intVal = new IntValue(inKey); - try { - Object setValue = properties.get(inKey); - if (setValue instanceof String) { - intVal.setString((String) setValue); - } else if (Number.class.isAssignableFrom(setValue - .getClass())) { - intVal.setObject(setValue); - } else { - intVal.setString(setValue.toString()); - } - int value = intVal.get(); - switch (validProp) { - case LockTimeout: - if (!fcPushed) { - fCfg = _broker.pushFetchConfiguration(); - fcPushed = true; - } - fCfg.setLockTimeout(value); - break; - case ReadLockLevel: - if (value != MixedLockLevels.LOCK_NONE - && value != fCfg.getReadLockLevel()) { - if (!fcPushed) { - fCfg = _broker.pushFetchConfiguration(); - fcPushed = true; - } - fCfg.setReadLockLevel(value); - } - break; - case WriteLockLevel: - if (value != MixedLockLevels.LOCK_NONE - && value != fCfg.getWriteLockLevel()) { - if (!fcPushed) { - fCfg = _broker.pushFetchConfiguration(); - fcPushed = true; - } - fCfg.setWriteLockLevel(value); - } - break; - } - } catch (Exception e) { - // silently ignore the property - } - break; // for(String inKey : inKeys) - } - } - } - } - return fcPushed; - } - - private boolean pushLockProperties(LockModeType mode, - Map properties) { - boolean fcPushed = false; // handle properties in map first - if (properties != null) { - fcPushed = setFetchConfigProperty(new FetchConfigProperty[] { - FetchConfigProperty.LockTimeout, - FetchConfigProperty.ReadLockLevel, - FetchConfigProperty.WriteLockLevel }, properties); - } + fPlan.addHints(properties); // override with the specific lockMode, if needed. - int setReadLevel = MixedLockLevelsHelper.toLockLevel(mode); - if (setReadLevel != MixedLockLevels.LOCK_NONE) { + if (mode != null && mode != LockModeType.NONE) { // Set overriden read lock level - FetchConfiguration fCfg = _broker.getFetchConfiguration(); - int curReadLevel = fCfg.getReadLockLevel(); - if (setReadLevel != curReadLevel) { - if (!fcPushed) { - fCfg = _broker.pushFetchConfiguration(); - fcPushed = true; - } - fCfg.setReadLockLevel(setReadLevel); - } - // Set overriden isolation level for pessimistic-read/write - switch (setReadLevel) { - case MixedLockLevels.LOCK_PESSIMISTIC_READ: - fcPushed = setIsolationForPessimisticLock(fCfg, fcPushed, - Connection.TRANSACTION_REPEATABLE_READ); - break; - - case MixedLockLevels.LOCK_PESSIMISTIC_WRITE: - case MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT: - fcPushed = setIsolationForPessimisticLock(fCfg, fcPushed, - Connection.TRANSACTION_SERIALIZABLE); - break; - - default: - } - } - return fcPushed; - } - - private boolean setIsolationForPessimisticLock(FetchConfiguration fCfg, - boolean fcPushed, int level) { - if (!fcPushed) { - fCfg = _broker.pushFetchConfiguration(); - fcPushed = true; - } - // TODO: refactoring under OPENJPA-957 -// ((JDBCFetchConfiguration) fCfg).setIsolation(level); - return fcPushed; - } - - private void popLockProperties(boolean fcPushed) { - if (fcPushed) { - _broker.popFetchConfiguration(); + LockModeType curReadLockMode = fPlan.getReadLockMode(); + if (mode != curReadLockMode) + fPlan.setReadLockMode(mode); } } - public Metamodel getMetamodel() { throw new UnsupportedOperationException( "JPA 2.0 - Method not yet implemented"); } - public void refresh(Object arg0, Map arg1) { - throw new UnsupportedOperationException( - "JPA 2.0 - Method not yet implemented"); - } - public void setProperty(String arg0, Object arg1) { throw new UnsupportedOperationException( "JPA 2.0 - Method not yet implemented"); } - - public T find(Class arg0, Object arg1, Map arg2) { - throw new UnsupportedOperationException( - "JPA 2.0 - Method not yet implemented"); - } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java index 07737f054..0a7119725 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java @@ -129,6 +129,29 @@ public interface FetchPlan { */ public void setHint(String key, Object value); + /** + * Sets the hint for the given key to the given value. + * + * @since 2.0.0 + */ + public void setHint(String key, Object value, boolean validThrowException); + + /** + * Adds the hint and the associated value to the list. + * + * @param name the name of the hint + * @param value the value of the hint + * @since 2.0.0 + */ + public void addHint(String name, Object value); + + /** + * Sets the hint keys and values currently set of this receiver. + * + * @since 2.0.0 + */ + public void addHints(Map hints); + /** * Gets the hint keys and values currently set of this receiver. * @@ -291,10 +314,10 @@ public interface FetchPlan { public int getLockTimeout(); /** - * The number of milliseconds to wait for a query, or -1 for no + * The number of milliseconds to wait for an object lock, or -1 for no * limit. */ - public FetchPlan setQueryTimeout(int timeout); + public FetchPlan setLockTimeout(int timeout); /** * The number of milliseconds to wait for a query, or -1 for no @@ -303,11 +326,11 @@ public interface FetchPlan { public int getQueryTimeout(); /** - * The number of milliseconds to wait for an object lock, or -1 for no + * The number of milliseconds to wait for a query, or -1 for no * limit. */ + public FetchPlan setQueryTimeout(int timeout); - public FetchPlan setLockTimeout(int timeout); /** * The lock level to use for locking loaded objects. */ @@ -327,7 +350,6 @@ public interface FetchPlan { * The lock level to use for locking dirtied objects. */ public FetchPlan setWriteLockMode(LockModeType mode); - /** * @deprecated cast to {@link FetchPlanImpl} instead. This diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java new file mode 100644 index 000000000..c353433e0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java @@ -0,0 +1,214 @@ +/* + * 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.persistence; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.persistence.LockModeType; + +import org.apache.openjpa.kernel.FetchConfigurationImpl; +import org.apache.openjpa.kernel.AbstractHintHandler; +import org.apache.openjpa.kernel.MixedLockLevels; +import org.apache.openjpa.lib.conf.ProductDerivations; +import org.apache.openjpa.lib.util.Localizer; + +/** + * Fetch plan hint handler. Handles openjpa.FetchPlan.*, + * javax.persistence.lock.* and javax.persistence.query.* hints. + * + * @since 2.0.0 + * @nojavadoc + */ +public class FetchPlanHintHandler extends AbstractHintHandler { + + private static final Localizer _loc = Localizer + .forPackage(FetchPlanHintHandler.class); + + protected static final String PREFIX_JPA = "javax.persistence."; + protected static final String PREFIX_FETCHPLAN = PREFIX_OPENJPA + + "FetchPlan."; + + // Valid defined product derivation prefixes + protected static final Set ValidProductPrefixes = + new HashSet(); + // JPA Specification 2.0 keys are mapped to equivalent FetchPlan keys + protected static final Map JavaxHintsMap = + new HashMap(); + // hints precedent definitions + protected static final Map PrecedenceMap = + new HashMap(); + + static { + // Initialize valid product prefixes from available product derivations. + for (String prefix : ProductDerivations.getConfigurationPrefixes()) { + ValidProductPrefixes.add(prefix); + } + // Initiali javax.persistence to openjpa.FetchPlan hint mapping. + JavaxHintsMap.put(PREFIX_JPA + "lock.timeout", PREFIX_FETCHPLAN + + "LockTimeout"); + JavaxHintsMap.put(PREFIX_JPA + "query.timeout", PREFIX_FETCHPLAN + + "QueryTimeout"); + // Initialize hint precendent order mapping from list. + String[][] precedenceMapList = { + { PREFIX_JPA + "lock.timeout", + PREFIX_FETCHPLAN + "LockTimeout", + PREFIX_OPENJPA + "LockTimeout" }, + + { PREFIX_JPA + "query.timeout", + PREFIX_FETCHPLAN + "QueryTimeout", + PREFIX_OPENJPA + "QueryTimeout" }, + + { PREFIX_FETCHPLAN + "Isolation", + PREFIX_JDBC + "TransactionIsolation" }, + + { PREFIX_FETCHPLAN + "EagerFetchMode", + PREFIX_JDBC + "EagerFetchMode" }, + + { PREFIX_FETCHPLAN + "FetchDirection", + PREFIX_JDBC + "FetchDirection" }, + + { PREFIX_FETCHPLAN + "JoinSyntax", + PREFIX_JDBC + "JoinSyntax" }, + + { PREFIX_FETCHPLAN + "LRSSizeAlgorithm", + PREFIX_FETCHPLAN + "LRSSize", + PREFIX_JDBC + "LRSSize" }, + + { PREFIX_FETCHPLAN + "ResultSetType", + PREFIX_JDBC + "ResultSetType" }, + + { PREFIX_FETCHPLAN + "SubclassFetchMode", + PREFIX_JDBC + "SubclassFetchMode" }, + + { PREFIX_FETCHPLAN + "ReadLockMode", + PREFIX_OPENJPA + "ReadLockLevel" }, + + { PREFIX_FETCHPLAN + "WriteLockMode", + PREFIX_OPENJPA + "WriteLockLevel" }, + + { PREFIX_FETCHPLAN + "FetchBatchSize", + PREFIX_OPENJPA + "FetchBatchSize" }, + + { PREFIX_FETCHPLAN + "MaxFetchDepth", + PREFIX_OPENJPA + "MaxFetchDepth" } + }; + for (String[] list : precedenceMapList) { + for (String hint : list) + PrecedenceMap.put(hint, list); + } + } + + protected FetchPlanImpl _fPlan; + + /** + * Constructor; supply delegate. + */ + public FetchPlanHintHandler(FetchPlanImpl fetchPlan) { + super((FetchConfigurationImpl) fetchPlan.getDelegate()); + _fPlan = fetchPlan; + } + + public boolean setHint(String hintName, Object value, + boolean validateThrowException) { + if (!hintName.startsWith(PREFIX_JPA) + && !ValidProductPrefixes.contains(getPrefixOf(hintName))) + return false; + return super.setHint(hintName, value, validateThrowException); + } + + protected boolean setHintInternal(String hintName, Object value, + boolean validateThrowException) { + boolean valueSet = false; + if (hintName.startsWith(PREFIX_FETCHPLAN)) { + if (hintName.endsWith("LockMode") + && !_fConfig.getContext().isActive()) { + _fConfig.setHint(hintName + ".Defer", toLockLevel(value), + false); + valueSet = true; + } else + valueSet = hintToSetter(_fPlan, hintName, value); + } else + _fConfig.setHint(hintName, value, validateThrowException); + return valueSet; + } + + protected String hintToKey(String key) { + // transform product derived prefix to openjpa prefix + if (!key.startsWith(PREFIX_OPENJPA) + && ValidProductPrefixes.contains(getPrefixOf(key))) + key = PREFIX_OPENJPA + key.substring(key.indexOf('.') + 1); + + // transform javax.persistence.* hints to fetch plan hints. + if (JavaxHintsMap.containsKey(key)) + key = JavaxHintsMap.get(key); + return key; + } + + protected boolean hasPrecedent(String key) { + boolean hasPrecedent = true; + String[] list = PrecedenceMap.get(key); + if (list != null) { + for (String hint : list) { + if (hint.equals(key)) + break; + // stop if a higher precedence hint has already defined + if (_fConfig.getHint(hint) != null) { + hasPrecedent = false; + break; + } + } + } + return hasPrecedent; + } + + protected void handleException(RuntimeException e) { + throw PersistenceExceptions.toPersistenceException(e); + } + + private Integer toLockLevel(Object value) { + Object origValue = value; + if (value instanceof String) { + // to accomodate alias name input in relationship with enum values + // e.g. "optimistic-force-increment" == + // LockModeType.OPTIMISTIC_FORCE_INCREMENT + String strValue = ((String) value).toUpperCase().replace('-', '_'); + value = Enum.valueOf(LockModeType.class, strValue); + } + if (value instanceof LockModeType) + value = MixedLockLevelsHelper.toLockLevel((LockModeType) value); + + Integer intValue = null; + if (value instanceof Integer) + intValue = (Integer) value; + if (intValue == null + || (intValue != MixedLockLevels.LOCK_NONE + && intValue != MixedLockLevels.LOCK_OPTIMISTIC + && intValue != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT + && intValue != MixedLockLevels.LOCK_PESSIMISTIC_READ + && intValue != MixedLockLevels.LOCK_PESSIMISTIC_WRITE + && intValue != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) + ) + throw new IllegalArgumentException(_loc.get("bad-lock-level", + origValue).getMessage()); + return intValue; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java index 648d4cf39..7c9d7be33 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java @@ -28,7 +28,6 @@ import javax.persistence.LockModeType; import org.apache.openjpa.kernel.DelegatingFetchConfiguration; import org.apache.openjpa.kernel.FetchConfiguration; -import org.apache.openjpa.kernel.MixedLockLevels; /** * Implements FetchPlan via delegation to FetchConfiguration. @@ -42,13 +41,14 @@ public class FetchPlanImpl implements FetchPlan { private final DelegatingFetchConfiguration _fetch; - + private FetchPlanHintHandler _hintHandler; /** * Constructor; supply delegate. */ public FetchPlanImpl(FetchConfiguration fetch) { _fetch = newDelegatingFetchConfiguration(fetch); + _hintHandler = new FetchPlanHintHandler(this); } /** @@ -275,8 +275,24 @@ public class FetchPlanImpl return _fetch.getHint(key); } + public void addHint(String key, Object value) { + _fetch.addHint(key, value); + } + public void setHint(String key, Object value) { - _fetch.setHint(key, value); + setHint(key, value, true); + } + + public void setHint(String key, Object value, boolean validThrowException) { + if( _hintHandler.setHint(key, value, validThrowException) ) + _fetch.addHint(key, value); + } + + public void addHints(Map hints) { + if (hints != null && hints.size() > 0) { + for (String name : hints.keySet()) + setHint(name, hints.get(name), false); + } } public Map getHints() { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java index 4e898631e..311272b43 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java @@ -1,11 +1,28 @@ +/* + * 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.persistence; import static org.apache.openjpa.kernel.QueryHints.HINT_IGNORE_PREPARED_QUERY; -import static org.apache.openjpa.kernel.QueryHints. - HINT_INVALIDATE_PREPARED_QUERY; +import static org.apache.openjpa.kernel.QueryHints + .HINT_INVALIDATE_PREPARED_QUERY; import static org.apache.openjpa.kernel.QueryHints.HINT_RESULT_COUNT; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Comparator; @@ -26,7 +43,6 @@ import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.StringDistance; - /** * Manages query hint keys and handles their values on behalf of a owning * {@link QueryImpl}. Uses specific knowledge of hint keys declared in @@ -81,15 +97,16 @@ import org.apache.openjpa.lib.util.StringDistance; * * @nojavadoc */ -public class HintHandler { +public class HintHandler extends FetchPlanHintHandler { + + private static final Localizer _loc = Localizer.forPackage( + HintHandler.class); + private final QueryImpl owner; private Map _hints; private Set _supportedKeys; private Set _supportedPrefixes; - static final String PREFIX_JPA = "javax.persistence."; - static final String PREFIX_FETCHPLAN = "openjpa.FetchPlan."; - // These keys are directly handled in {@link QueryImpl} class. // Declaring a public static final String variable in this class will // make it register as a supported hint key @@ -103,21 +120,8 @@ public class HintHandler { public static final String HINT_AGGREGATE_LISTENERS = "openjpa.AggregateListeners"; - // JPA Specification 2.0 keys are mapped to equivalent FetchPlan keys - public static Map _jpaKeys = new TreeMap(); - static { - _jpaKeys.put(addPrefix(PREFIX_JPA, "query.timeout"), - addPrefix(PREFIX_FETCHPLAN, "QueryTimeout")); - _jpaKeys.put(addPrefix(PREFIX_JPA, "lock.timeout"), - addPrefix(PREFIX_FETCHPLAN, "LockTimeout")); - } - - private static final String DOT = "."; - private static final String BLANK = ""; - private static final Localizer _loc = Localizer.forPackage( - HintHandler.class); - HintHandler(QueryImpl impl) { + super((FetchPlanImpl)impl.getFetchPlan()); owner = impl; } @@ -151,9 +155,8 @@ public class HintHandler { .getLog(OpenJPAConfiguration.LOG_RUNTIME); String possible = StringDistance.getClosestLevenshteinDistance(hint, getSupportedHints()); - if (log.isWarnEnabled()) { + if (log.isWarnEnabled()) log.warn(_loc.get("bad-query-hint", hint, possible)); - } return (isKnownHintPrefix(hint)) ? null : Boolean.FALSE; } @@ -176,7 +179,7 @@ public class HintHandler { Reflection.getBeanStylePropertyNames( owner.getFetchPlan().getClass()))); - _supportedKeys.addAll(_jpaKeys.keySet()); + _supportedKeys.addAll(JavaxHintsMap.keySet()); _supportedKeys.addAll(Reflection.getFieldValues( HintHandler.class, @@ -212,157 +215,76 @@ public class HintHandler { return getSupportedHints().contains(key); } - /** - * Affirms the given key has a prefix that matches with any of the - * supported prefixes. - */ - private boolean isSupportedPrefix(String key) { - return getKnownPrefixes().contains(getPrefixOf(key)); - } - - static Set addPrefix(String prefix, Set original) { - Set result = new TreeSet(); - String join = prefix.endsWith(DOT) ? BLANK : DOT; - for (String o : original) - result.add(prefix + join + o); - return result; - } - - static String addPrefix(String prefix, String original) { - String join = prefix.endsWith(DOT) ? BLANK : DOT; - return prefix + join + original; - } - - private static String removePrefix(String key, String prefix) { - if (prefix == null) - return key; - if (!prefix.endsWith(DOT)) - prefix = prefix + DOT; - if (key != null && key.startsWith(prefix)) - return key.substring(prefix.length()); - return key; - } - - static String getPrefixOf(String key) { - int index = key == null ? -1 : key.indexOf(DOT); - return (index != -1) ? key.substring(0,index) : key; - } - private boolean isKnownHintPrefix(String key) { String prefix = getPrefixOf(key); return getKnownPrefixes().contains(prefix); } - - public static boolean hasPrefix(String key, String prefix) { - if (key == null || prefix == null) - return false; - if (!prefix.endsWith(DOT)) - prefix = prefix + DOT; - return key.startsWith(prefix); - } - + public void setHint(String key, Object value) { owner.lock(); try { - setHintInternal(key, value); + Boolean record = record(key, value); + if (record == Boolean.FALSE) + return; + FetchPlan plan = owner.getFetchPlan(); + if (record == null) { + plan.setHint(key, value); + return; + } + // request to throw IllegalArgumentException, if needed. + if (setHint(key, value, true)) + plan.addHint(key, value); } finally { owner.unlock(); } } - private void setHintInternal(String key, Object value) { - Boolean record = record(key, value); - FetchPlan plan = owner.getFetchPlan(); + protected boolean setHintInternal(String key, Object value, + boolean validateThrowException) { ClassLoader loader = owner.getDelegate().getBroker().getClassLoader(); - if (record == Boolean.FALSE) - return; - if (record == null) { - plan.setHint(key, value); - return; - } - try { - if (HINT_SUBCLASSES.equals(key)) { - if (value instanceof String) - value = Boolean.valueOf((String) value); - owner.setSubclasses(((Boolean) value).booleanValue()); - } else if (HINT_FILTER_LISTENER.equals(key)) - owner.addFilterListener(Filters.hintToFilterListener(value, - loader)); - else if (HINT_FILTER_LISTENERS.equals(key)) { - FilterListener[] arr = Filters.hintToFilterListeners(value, - loader); - for (int i = 0; i < arr.length; i++) - owner.addFilterListener(arr[i]); - } else if (HINT_AGGREGATE_LISTENER.equals(key)) - owner.addAggregateListener(Filters.hintToAggregateListener( - value, loader)); - else if (HINT_AGGREGATE_LISTENERS.equals(key)) { - AggregateListener[] arr = Filters.hintToAggregateListeners( - value, loader); - for (int i = 0; i < arr.length; i++) - owner.addAggregateListener(arr[i]); - } else if (isFetchPlanHint(key)) { - if (requiresTransaction(key)) - plan.setHint(key, value); - else - hintToSetter(plan, getFetchPlanProperty(key), value); - } else if (HINT_RESULT_COUNT.equals(key)) { - int v = (Integer)Filters.convert(value, Integer.class); - if (v < 0) - throw new ArgumentException(_loc.get("bad-query-hint-value", - key, value), null, null, false); - plan.setHint(key, v); - } else if (HINT_INVALIDATE_PREPARED_QUERY.equals(key)) { - plan.setHint(key, Filters.convert(value, Boolean.class)); - owner.invalidatePreparedQuery(); - } else if (HINT_IGNORE_PREPARED_QUERY.equals(key)) { - plan.setHint(key, Filters.convert(value, Boolean.class)); - owner.ignorePreparedQuery(); - } else { // default - plan.setHint(key, value); - } - return; - } catch (IllegalArgumentException iae) { - throw new ArgumentException(_loc.get("bad-query-hint-value", - key, value), null, null, false); - } catch (ClassCastException ce) { - throw new ArgumentException(_loc.get("bad-query-hint-value", - key, ce.getMessage()), null, null, false); - } catch (Exception e) { - throw PersistenceExceptions.toPersistenceException(e); + FetchPlan fPlan = owner.getFetchPlan(); + boolean objectSet = true; + if (HINT_SUBCLASSES.equals(key)) { + if (value instanceof String) + value = Boolean.valueOf((String) value); + owner.setSubclasses(((Boolean) value).booleanValue()); + } else if (HINT_FILTER_LISTENER.equals(key)) + owner.addFilterListener(Filters.hintToFilterListener(value, + loader)); + else if (HINT_FILTER_LISTENERS.equals(key)) { + FilterListener[] arr = Filters.hintToFilterListeners(value, loader); + for (int i = 0; i < arr.length; i++) + owner.addFilterListener(arr[i]); + } else if (HINT_AGGREGATE_LISTENER.equals(key)) + owner.addAggregateListener(Filters.hintToAggregateListener(value, + loader)); + else if (HINT_AGGREGATE_LISTENERS.equals(key)) { + AggregateListener[] arr = Filters.hintToAggregateListeners(value, + loader); + for (int i = 0; i < arr.length; i++) + owner.addAggregateListener(arr[i]); + } else if (HINT_RESULT_COUNT.equals(key)) { + int v = (Integer) Filters.convert(value, Integer.class); + if (v < 0) + throw new ArgumentException(_loc.get("bad-query-hint-value", + key, value), null, null, false); + fPlan.setHint(key, v); + objectSet = false; + } else if (HINT_INVALIDATE_PREPARED_QUERY.equals(key)) { + fPlan.setHint(key, Filters.convert(value, Boolean.class)); + owner.invalidatePreparedQuery(); + objectSet = false; + } else if (HINT_IGNORE_PREPARED_QUERY.equals(key)) { + fPlan.setHint(key, Filters.convert(value, Boolean.class)); + owner.ignorePreparedQuery(); + objectSet = false; + } else { // default + fPlan.setHint(key, value); + objectSet = false; } + return objectSet; } - - private boolean isFetchPlanHint(String key) { - return key.startsWith(PREFIX_FETCHPLAN) - || (_jpaKeys.containsKey(key) && isFetchPlanHint(_jpaKeys.get(key))); - } - - private boolean requiresTransaction(String key) { - return key.endsWith("LockMode"); - } - - private String getFetchPlanProperty(String key) { - if (key.startsWith(PREFIX_FETCHPLAN)) - return removePrefix(key, PREFIX_FETCHPLAN); - else if (_jpaKeys.containsKey(key)) - return getFetchPlanProperty(_jpaKeys.get(key)); - else - return key; - } - - private void hintToSetter(FetchPlan fetchPlan, String k, Object value) { - if (fetchPlan == null || k == null) - return; - Method setter = Reflection.findSetter(fetchPlan.getClass(), k, true); - Class paramType = setter.getParameterTypes()[0]; - if (Enum.class.isAssignableFrom(paramType) && value instanceof String) - value = Enum.valueOf(paramType, (String) value); - - Filters.hintToSetter(fetchPlan, k, value); - } - public static class HintKeyComparator implements Comparator { public int compare(String s1, String s2) { if (getPrefixOf(s1).equals(getPrefixOf(s2))) { @@ -372,12 +294,26 @@ public class HintHandler { } else return s1.compareTo(s2); } - + public int countDots(String s) { if (s == null || s.length() == 0) return 0; int index = s.indexOf(DOT); - return (index == -1) ? 0 : countDots(s.substring(index+1)) + 1; + return (index == -1) ? 0 : countDots(s.substring(index + 1)) + 1; } } + + protected String hintToKey(String key) { + // Let superclass performs key transformation when fPlan.setHint() + // is called. + return key; + } + + private Set addPrefix(String prefix, Set original) { + Set result = new TreeSet(); + String join = prefix.endsWith(DOT) ? BLANK : DOT; + for (String o : original) + result.add(prefix + join + o); + return result; + } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java index 5bdfea87f..b54caad29 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java @@ -37,10 +37,10 @@ public class MixedLockLevelsHelper { if (mode == null || mode == LockModeType.NONE) return MixedLockLevels.LOCK_NONE; if (mode == LockModeType.READ || mode == LockModeType.OPTIMISTIC) - return MixedLockLevels.LOCK_READ; + return MixedLockLevels.LOCK_OPTIMISTIC; if (mode == LockModeType.WRITE || mode == LockModeType.OPTIMISTIC_FORCE_INCREMENT) - return MixedLockLevels.LOCK_WRITE; + return MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT; if (mode == LockModeType.PESSIMISTIC_READ) return MixedLockLevels.LOCK_PESSIMISTIC_READ; if (mode == LockModeType.PESSIMISTIC_WRITE) @@ -53,11 +53,11 @@ public class MixedLockLevelsHelper { */ public static LockModeType fromLockLevel(int level) { if (level < MixedLockLevels.LOCK_OPTIMISTIC) - return null; + return LockModeType.NONE; if (level < MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT) - return LockModeType.READ; + return LockModeType.OPTIMISTIC; if (level < MixedLockLevels.LOCK_PESSIMISTIC_READ) - return LockModeType.WRITE; + return LockModeType.OPTIMISTIC_FORCE_INCREMENT; if (level < MixedLockLevels.LOCK_PESSIMISTIC_WRITE) return LockModeType.PESSIMISTIC_READ; if (level < MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) diff --git a/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties b/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties index e1d63b6e1..49e72870d 100644 --- a/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties +++ b/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties @@ -1,171 +1,175 @@ -# 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. - -close-invoked: You have closed the EntityManager, though the persistence \ - context will remain active until the current transaction commits. -no-managed-trans: There is no managed transaction in progress to sync this \ - EntityManager with. -get-managed-trans: You cannot access the EntityTransaction when using managed \ - transactions. -trans-ctx-notactive: When using a persistence context type of TRANSACTION, you \ - can only perform this operation during an active transaction. -not-entity: The class "{0}" is not an entity. -not-managed: Object "{0}" is not managed by this context. -parse-class: Parsing class "{0}". -parse-package: Parsing package "{0}". -parse-sequence: Parsing sequence "{0}". -parse-query: Parsing query "{0}". -parse-native-query: Parsing native query "{0}". -dup-metadata: Found duplicate metadata or mapping for "{0}". Ignoring. -dup-sequence: Found duplicate generator "{0}" in "{1}". Ignoring. -override-sequence: Found duplicate generator "{0}" in "{1}". Overriding \ - previous definition. -dup-query: Ignoring duplicate query "{0}" in "{1}". A query with the same name \ - been already declared in "{2}". -override-query: Found duplicate query "{0}" in "{1}". Overriding previous \ - definition. -no-seq-name: The sequence generator in "{0}" must declare a name. -no-query-name: The named query in "{0}" must declare a name. -no-native-query-name: The named native query in "{0}" must declare a name. -no-query-string: The named query "{0}" in "{1}" must declare a query string. -no-native-query-string: The named native query "{0}" in "{1}" must declare a \ - query string. -already-pers: Field "{0}" cannot be annotated by two persistence strategy \ - annotations. -unsupported: OpenJPA does not yet support "{1}" as used in "{0}". -bad-meta-anno: The type of field "{0}" isn''t supported by declared \ - persistence strategy "{1}". Please choose a different strategy. -no-pers-strat: Fields "{0}" are not a default persistent type, and do not \ - have any annotations indicating their persistence strategy. If you do \ - not want these fields to be persisted, annotate them with @Transient. -generator-bad-strategy: "{0}" declares generator name "{1}", but uses the AUTO \ - generation type. The only valid generator names under AUTO are "uuid-hex" \ - and "uuid-string". -unnamed-fg: "{0}" declares an unnamed fetch group. All fetch groups \ - must have names. -bad-fg-field: Fetch group "{0}" in type "{1}" includes field "{2}", but \ - this field is not declared in "{1}", or is not persistent. Currently, \ - OpenJPA only supports declared fields in fetch groups. -missing-included-fg:"{0}" declares a fetch group "{1}" includes "{2}". But \ - the included fetch group "{2}" can not be found in "{0}". Currently, all \ - included fetch groups must be declared within the same entity scope. -not-update-delete-query: Cannot perform an update or delete operation \ - on select query: "{0}". -not-select-query: Cannot perform a select on update or delete query: "{0}". -no-results: Query did not return any results: "{0}". -mult-results: Query returned multiple results: "{0}". -no-pos-named-params-mix: Cannot mix named and positional parameters in query \ - "{0}". -bad-query-hint: "{0}" is not a supported query hint. May be you meant "{1}"? -bad-query-hint-value: Invalid value specified for query hint "{0}": {1} -detached: Cannot perform this operation on detached entity "{0}". -removed: Cannot perform this operation on removed entity "{0}". -bad-alias: There is no known entity class for entity name "{0}". It is \ - possible that the corresponding class has not yet been registered in the \ - JVM. -naming-exception: A NamingException was thrown while obtaining the \ - factory at "{0}" from JNDI. -bad-jar-name: The jar resource "{0}" cannot be loaded. -missing-xml-config: The specified XML resource "{0}" for persistence unit \ - "{1}" can''t be found in your class path. -cantload-xml-config: The specified XML resource "{0}" for persistence unit \ - "{1}" can''t be parsed. -unknown-provider: Persistence provider "{2}" specified in persistence unit \ - "{1}" in "{0}" is not a recognized provider. -illegal-index: The parameter index {0} is invalid. Parameters must be \ - integers starting at 1. -conf-load: Setting the following properties from "{0}" into configuration: {1} -no-named-field: Type "{0}" does not have a managed field named "{1}". -unsupported-tag: OpenJPA does not currently support XML element "{0}". Ignoring. -no-class: No class attribute was specified. -invalid-id-class: Could not load id class "{1}" for type "{0}". -invalid-attr: Could not find property/field with the name "{0}" in type "{1}". -ser-class: Writing class "{0}". -ser-cls-query: Writing query "{1}" in class "{0}". -ser-query: Writing query "{1}". -ser-sequence: Writing sequence "{0}". -no-sql: You must provide a SQL string when creating a native query. -no-named-params: Named parameter "{0}" is invalid for native query "{1}". \ - Use only 1-based positional parameter in native queries. -bad-pos-params: Positional parameter "{0}" is invalid for native query "{1}". \ - Use only 1-based positional parameter in native queries. -bad-param-type: The parameter "{1}" in query "{0}" is set to a value of type \ - "{2}", but the parameter binds to a field of type "{3}". -missing-param-name: The parameter "{1}" in query "{0}" is not found in the \ - available list of parameters "{2}". -bad-em-prop: Invalid EntityManager property passed to createEntityManager. \ - Key: "{0}", Value: "{1}". -bad-em-props: Invalid EntityManager properties passed to createEntityManager. \ - See nested exceptions for details. -system-listener-err: An error occurred invoking system entity listener \ - callback on instance "{0}". -no-transaction: Cannot perform operation with no transaction. -multiple-methods-on-callback: Class "{0}" declares method "{1}" as well \ - as "{2}" for handling the same "{3}" callback. -unloadable-provider: WARNING: Unable to load persistence provider "{0}" due \ - to "{1}" -unrecognized-provider: WARNING: Found unrecognized persistence provider "{0}" \ - in place of OpenJPA provider. This provider''s properties will not be used. -cant-convert-brokerfactory: Unable to convert EntityManagerFactory of type \ - "{0}" into a BrokerFactory. -cant-convert-broker: Unable to convert EntityManager of type "{0}" into a \ - Broker. -map-persistent-type-names: Mapping resource location "{0}" to persistent \ - types "{1}". -map-persistent-types-skipping-non-url: Skipping persistent type location \ - association for location "{0}" since it is not a URL. -map-persistent-types-skipping-class: Skipping persistent type location \ - association for location "{0}" since it is a class, and will not \ - need to be re-parsed later. -no-setter-for-getter: No setter was found for method {0} in type {1} while \ - searching for persistent properties. This method will be ignored. If you \ - intended for this to be persistent, please add a corresponding setter, \ - or switch to field access for this type hierarchy. -transformer-registration-error: An error occurred while registering a \ - ClassTransformer with {0}. The error has been consumed. To see it, set \ - your openjpa.Runtime log level to TRACE. Load-time class transformation \ - will not be available. -transformer-registration-error-ex: An error occurred while registering a \ - ClassTransformer with {0}. The error is logged along with this warning. \ - Load-time class transformation will not be available. - -EntityManagerFactory-name: EntityManagerFactory implementation -EntityManagerFactory-desc: Allows extension of standard \ - org.apache.openjpa.persistence.EntityManagerFactoryImpl for custom behavior. -EntityManagerFactory-type: General -EntityManagerFactory-cat: Persistence.Advanced -EntityManagerFactory-displayorder: 50 -EntityManagerFactory-expert: true -EntityManagerFactory-interface: org.apache.openjpa.persistence.EntityManagerFactoryImpl -param-style-mismatch: Query "{0}" is declared with named parameters "{1}" but \ - actual parameters "{2}" are bound by position. -param-missing: Parameter "{0}" declared in "{1}" but is missing from the bound \ - parameters "{2}". -param-extra: Parameter "{0}" is bound to "{1}" but is missing from the \ - declared parameters "{2}". -param-type-mismatch: Parameter "{0}" declared in "{1}" is set to value of \ - "{2}" of type "{3}", but this parameter is bound to a field of type "{4}". -param-type-null: Parameter "{0}" declared in "{1}" is set to null, \ - but this parameter is bound to a field of primitive type "{2}". -version-check-error: An error occurred while attempting to determine the \ - version of "{0}". -no-result: Query "{0}" selected no result, but expected unique result. -non-unique-result: Query "{0}" selected {1} results, but expected unique result. -unwrap-em-invalid: EntityManager can not be unwrapped to an instance of "{0}". -unwrap-query-invalid: Query can not be unwrapped to an instance of "{0}". -invalid_entity_argument: Object being locked must be an valid and not detached \ - entity. +# 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. + +close-invoked: You have closed the EntityManager, though the persistence \ + context will remain active until the current transaction commits. +no-managed-trans: There is no managed transaction in progress to sync this \ + EntityManager with. +get-managed-trans: You cannot access the EntityTransaction when using managed \ + transactions. +trans-ctx-notactive: When using a persistence context type of TRANSACTION, you \ + can only perform this operation during an active transaction. +not-entity: The class "{0}" is not an entity. +not-managed: Object "{0}" is not managed by this context. +parse-class: Parsing class "{0}". +parse-package: Parsing package "{0}". +parse-sequence: Parsing sequence "{0}". +parse-query: Parsing query "{0}". +parse-native-query: Parsing native query "{0}". +dup-metadata: Found duplicate metadata or mapping for "{0}". Ignoring. +dup-sequence: Found duplicate generator "{0}" in "{1}". Ignoring. +override-sequence: Found duplicate generator "{0}" in "{1}". Overriding \ + previous definition. +dup-query: Ignoring duplicate query "{0}" in "{1}". A query with the same name \ + been already declared in "{2}". +override-query: Found duplicate query "{0}" in "{1}". Overriding previous \ + definition. +no-seq-name: The sequence generator in "{0}" must declare a name. +no-query-name: The named query in "{0}" must declare a name. +no-native-query-name: The named native query in "{0}" must declare a name. +no-query-string: The named query "{0}" in "{1}" must declare a query string. +no-native-query-string: The named native query "{0}" in "{1}" must declare a \ + query string. +already-pers: Field "{0}" cannot be annotated by two persistence strategy \ + annotations. +unsupported: OpenJPA does not yet support "{1}" as used in "{0}". +bad-meta-anno: The type of field "{0}" isn''t supported by declared \ + persistence strategy "{1}". Please choose a different strategy. +no-pers-strat: Fields "{0}" are not a default persistent type, and do not \ + have any annotations indicating their persistence strategy. If you do \ + not want these fields to be persisted, annotate them with @Transient. +generator-bad-strategy: "{0}" declares generator name "{1}", but uses the AUTO \ + generation type. The only valid generator names under AUTO are "uuid-hex" \ + and "uuid-string". +unnamed-fg: "{0}" declares an unnamed fetch group. All fetch groups \ + must have names. +bad-fg-field: Fetch group "{0}" in type "{1}" includes field "{2}", but \ + this field is not declared in "{1}", or is not persistent. Currently, \ + OpenJPA only supports declared fields in fetch groups. +missing-included-fg:"{0}" declares a fetch group "{1}" includes "{2}". But \ + the included fetch group "{2}" can not be found in "{0}". Currently, all \ + included fetch groups must be declared within the same entity scope. +not-update-delete-query: Cannot perform an update or delete operation \ + on select query: "{0}". +not-select-query: Cannot perform a select on update or delete query: "{0}". +no-results: Query did not return any results: "{0}". +mult-results: Query returned multiple results: "{0}". +no-pos-named-params-mix: Cannot mix named and positional parameters in query \ + "{0}". +bad-query-hint: "{0}" is not a supported query hint. May be you meant "{1}"? +bad-query-hint-value: Invalid value specified for query hint "{0}": {1} +detached: Cannot perform this operation on detached entity "{0}". +removed: Cannot perform this operation on removed entity "{0}". +bad-alias: There is no known entity class for entity name "{0}". It is \ + possible that the corresponding class has not yet been registered in the \ + JVM. +naming-exception: A NamingException was thrown while obtaining the \ + factory at "{0}" from JNDI. +bad-jar-name: The jar resource "{0}" cannot be loaded. +missing-xml-config: The specified XML resource "{0}" for persistence unit \ + "{1}" can''t be found in your class path. +cantload-xml-config: The specified XML resource "{0}" for persistence unit \ + "{1}" can''t be parsed. +unknown-provider: Persistence provider "{2}" specified in persistence unit \ + "{1}" in "{0}" is not a recognized provider. +illegal-index: The parameter index {0} is invalid. Parameters must be \ + integers starting at 1. +conf-load: Setting the following properties from "{0}" into configuration: {1} +no-named-field: Type "{0}" does not have a managed field named "{1}". +unsupported-tag: OpenJPA does not currently support XML element "{0}". Ignoring. +no-class: No class attribute was specified. +invalid-id-class: Could not load id class "{1}" for type "{0}". +invalid-attr: Could not find property/field with the name "{0}" in type "{1}". +ser-class: Writing class "{0}". +ser-cls-query: Writing query "{1}" in class "{0}". +ser-query: Writing query "{1}". +ser-sequence: Writing sequence "{0}". +no-sql: You must provide a SQL string when creating a native query. +no-named-params: Named parameter "{0}" is invalid for native query "{1}". \ + Use only 1-based positional parameter in native queries. +bad-pos-params: Positional parameter "{0}" is invalid for native query "{1}". \ + Use only 1-based positional parameter in native queries. +bad-param-type: The parameter "{1}" in query "{0}" is set to a value of type \ + "{2}", but the parameter binds to a field of type "{3}". +missing-param-name: The parameter "{1}" in query "{0}" is not found in the \ + available list of parameters "{2}". +bad-em-prop: Invalid EntityManager property passed to createEntityManager. \ + Key: "{0}", Value: "{1}". +bad-em-props: Invalid EntityManager properties passed to createEntityManager. \ + See nested exceptions for details. +system-listener-err: An error occurred invoking system entity listener \ + callback on instance "{0}". +no-transaction: Cannot perform operation with no transaction. +multiple-methods-on-callback: Class "{0}" declares method "{1}" as well \ + as "{2}" for handling the same "{3}" callback. +unloadable-provider: WARNING: Unable to load persistence provider "{0}" due \ + to "{1}" +unrecognized-provider: WARNING: Found unrecognized persistence provider "{0}" \ + in place of OpenJPA provider. This provider''s properties will not be used. +cant-convert-brokerfactory: Unable to convert EntityManagerFactory of type \ + "{0}" into a BrokerFactory. +cant-convert-broker: Unable to convert EntityManager of type "{0}" into a \ + Broker. +map-persistent-type-names: Mapping resource location "{0}" to persistent \ + types "{1}". +map-persistent-types-skipping-non-url: Skipping persistent type location \ + association for location "{0}" since it is not a URL. +map-persistent-types-skipping-class: Skipping persistent type location \ + association for location "{0}" since it is a class, and will not \ + need to be re-parsed later. +no-setter-for-getter: No setter was found for method {0} in type {1} while \ + searching for persistent properties. This method will be ignored. If you \ + intended for this to be persistent, please add a corresponding setter, \ + or switch to field access for this type hierarchy. +transformer-registration-error: An error occurred while registering a \ + ClassTransformer with {0}. The error has been consumed. To see it, set \ + your openjpa.Runtime log level to TRACE. Load-time class transformation \ + will not be available. +transformer-registration-error-ex: An error occurred while registering a \ + ClassTransformer with {0}. The error is logged along with this warning. \ + Load-time class transformation will not be available. + +EntityManagerFactory-name: EntityManagerFactory implementation +EntityManagerFactory-desc: Allows extension of standard \ + org.apache.openjpa.persistence.EntityManagerFactoryImpl for custom behavior. +EntityManagerFactory-type: General +EntityManagerFactory-cat: Persistence.Advanced +EntityManagerFactory-displayorder: 50 +EntityManagerFactory-expert: true +EntityManagerFactory-interface: org.apache.openjpa.persistence.EntityManagerFactoryImpl +param-style-mismatch: Query "{0}" is declared with named parameters "{1}" but \ + actual parameters "{2}" are bound by position. +param-missing: Parameter "{0}" declared in "{1}" but is missing from the bound \ + parameters "{2}". +param-extra: Parameter "{0}" is bound to "{1}" but is missing from the \ + declared parameters "{2}". +param-type-mismatch: Parameter "{0}" declared in "{1}" is set to value of \ + "{2}" of type "{3}", but this parameter is bound to a field of type "{4}". +param-type-null: Parameter "{0}" declared in "{1}" is set to null, \ + but this parameter is bound to a field of primitive type "{2}". +version-check-error: An error occurred while attempting to determine the \ + version of "{0}". +no-result: Query "{0}" selected no result, but expected unique result. +non-unique-result: Query "{0}" selected {1} results, but expected unique result. +unwrap-em-invalid: EntityManager can not be unwrapped to an instance of "{0}". +unwrap-query-invalid: Query can not be unwrapped to an instance of "{0}". +invalid_entity_argument: Object being locked must be an valid and not detached \ + entity. +bad-lock-level: Invalid lock mode/level. Valid values are \ + "none"(0), "optimistic"(10), "optimistic-force-increment"(20), \ + "pessimistic-read"(30), "pessimistic-write"(40) or \ + "pessimistic-force-increment"(50). Specified value: {0}. diff --git a/openjpa-project/src/doc/manual/jpa_overview_query.xml b/openjpa-project/src/doc/manual/jpa_overview_query.xml index 900576564..da797c4f8 100644 --- a/openjpa-project/src/doc/manual/jpa_overview_query.xml +++ b/openjpa-project/src/doc/manual/jpa_overview_query.xml @@ -814,6 +814,40 @@ hints={ @QueryHint (name="openjpa.hint.OptimizeResultCount", value="2"), +
+ + Handling of Multiple Similar Query Hints + + +When similar hints in different prefix scopes are specified in a query, +the following prefix precedence order is used to select the effective hint: + + +javax.persistence.* + + +openjpa.FetchPlan.* + + +openjpa.jdbc.* + + +openjpa.* + + + + +... +Query q = em.createQuery(.....); +q.setHint("openjpa.FetchPlan.LockTimeout", 1000); +q.setHint("javax.persistence.lock.timeout", 2000); +q.setHint("openjpa.LockTimeout", 3000); +// Lock time out of 2000 ms is in effect for query q +... + + + +
diff --git a/openjpa-project/src/doc/manual/ref_guide_conf.xml b/openjpa-project/src/doc/manual/ref_guide_conf.xml index a0dc9a127..85794c8e7 100644 --- a/openjpa-project/src/doc/manual/ref_guide_conf.xml +++ b/openjpa-project/src/doc/manual/ref_guide_conf.xml @@ -1,4048 +1,4057 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<chapter id="ref_guide_conf"> - <title> - Configuration - - - - configuration - - -
- - Introduction - - -This chapter describes the OpenJPA configuration framework. It concludes with -descriptions of all the configuration properties recognized by OpenJPA. You may -want to browse these properties now, but it is not necessary. Most of them will -be referenced later in the documentation as we explain the various features they -apply to. - -
-
- - Runtime Configuration - - - - configuration - - - runtime - - - -The OpenJPA runtime includes a comprehensive system of configuration defaults -and overrides: - - - - - - - openjpa.xml - - -OpenJPA first looks for an optional openjpa.xml resource. -OpenJPA searches for this resource in each top-level directory of your -CLASSPATH. OpenJPA will also find the resource if you place it within -a META-INF directory in any top-level directory of the -CLASSPATH. The openjpa.xml resource -contains property settings in -JPA's XML format. - - - - -You can customize the name or location of the above resource by specifying the -correct resource path in the openjpa.properties System -property. - - - - -You can override any value defined in the above resource by setting the System -property of the same name to the desired value. - - - - - - - Persistence - - - createEntityManagerFactory - - -In JPA, the values in the standard META-INF/persistence.xml - bootstrapping file used by the -Persistence - class at runtime override the values in the above resource, as well as -any System property settings. The Map passed to -Persistence.createEntityManagerFactory at runtime also -overrides previous settings, including properties defined in -persistence.xml. - - - - -When using JCA deployment the config-property values in your -ra.xml file override other settings. - - - - -All OpenJPA command-line tools accept flags that allow you to specify the -configuration resource to use, and to override any property. - describes these flags. - - - - - -Internally, the OpenJPA runtime environment and development -tools manipulate property settings through a general - -Configuration interface, and in particular its - -OpenJPAConfiguration and - -JDBCConfiguration subclasses. For advanced -customization, OpenJPA's extended runtime interfaces and its development tools -allow you to access these interfaces directly. See the -Javadoc for details. - - -
-
- - Command Line Configuration - - - - configuration - - - command line - - - -OpenJPA development tools share the same set of configuration defaults and -overrides as the runtime system. They also allow you to specify property values -on the command line: - - - - --properties/-p <configuration file or resource>: Use -the -properties flag, or its shorter -p -form, to specify a configuration file to use. Note that OpenJPA always searches -the default file locations described above, so this flag is only needed when you -do not have a default resource in place, or when you wish to override the -defaults. The given value can be the path to a file, or the resource name of a -file somewhere in the CLASSPATH. OpenJPA will search the -given location as well as the location prefixed by META-INF/ -. Thus, to point an OpenJPA tool at -META-INF/my-persistence.xml, you can use: - - -<tool> -p my-persistence.xml - - -If you want to run a tool against just one particular persistence unit in -a configuration file, you can do so by specifying an anchor along with the -resource. If you do not specify an anchor, the tools will run against all -the persistence units defined within the specified resource, or the default -resource if none is specified. If the persistence unit is defined within -the default resource location, then you can just specify the raw anchor itself: - - -<tool> -p my-persistence.xml#sales-persistence-unit -<tool> -p #invoice-persistence-unit - - - - --<property name> <property value>: Any -configuration property that you can specify in a configuration file can be -overridden with a command line flag. The flag name is always the last token of -the corresponding property name, with the first letter in either upper or lower -case. For example, to override the openjpa.ConnectionUserName -property, you could pass the -connectionUserName <value> - flag to any tool. Values set this way override both the values in the -configuration file and values set via System properties. - - - -
- - Code Formatting - - - - code formatting - - - -Some OpenJPA development tools generate Java code. These tools share a common -set of command-line flags for formatting their output to match your coding -style. All code formatting flags can begin with either the codeFormat - or cf prefix. - - - - --codeFormat./-cf.tabSpaces <spaces>: The number of -spaces that make up a tab, or 0 to use tab characters. Defaults to using tab -characters. - - - - --codeFormat./-cf.spaceBeforeParen <true/t | false/f>: -Whether or not to place a space before opening parentheses on method calls, if -statements, loops, etc. Defaults to false. - - - - --codeFormat./-cf.spaceInParen <true/t | false/f>: -Whether or not to place a space within parentheses; i.e. method( arg) -. Defaults to false. - - - - --codeFormat./-cf.braceOnSameLine <true/t | false/f>: -Whether or not to place opening braces on the same line as the declaration that -begins the code block, or on the next line. Defaults to true -. - - - - --codeFormat./-cf.braceAtSameTabLevel <true/t | false/f> -: When the braceOnSameLine option is disabled, you can choose -whether to place the brace at the same tab level of the contained code. Defaults -to false. - - - - --codeFormat./-cf.scoreBeforeFieldName <true/t | false/f> -: Whether to prefix an underscore to names of private member -variables. Defaults to false. - - - - --codeFormat./-cf.linesBetweenSections <lines>: The -number of lines to skip between sections of code. Defaults to 1. - - - - - - Code Formatting with the Application Id Tool - - -java org.apache.openjpa.enhance.ApplicationIdTool -cf.spaceBeforeParen true -cf.tabSpaces 4 - - -
-
-
- - Plugin Configuration - - - - configuration - - - plugins - - - - - plugins - - - configuration - - - -Because OpenJPA is a highly customizable environment, many configuration -properties relate to the creation and configuration of system plugins. Plugin -properties have a syntax very similar to that of Java 5 annotations. They allow -you to specify both what class to use for the plugin and how to configure the -public fields or bean properties of the instantiated plugin instance. The -easiest way to describe the plugin syntax is by example: - - -OpenJPA has a pluggable L2 caching mechanism that is controlled by the -openjpa.DataCache configuration property. Suppose that you have -created a new class, com.xyz.MyDataCache, that you want -OpenJPA to use for caching. You've made instances of MyDataCache - configurable via two methods, setCacheSize(int size) - and setRemoteHost(String host). The -sample below shows how you would tell OpenJPA to use an instance of your custom -plugin with a max size of 1000 and a remote host of cacheserver -. - - -<property name="openjpa.DataCache" - value="com.xyz.MyDataCache(CacheSize=1000, RemoteHost=cacheserver)"/> - - -As you can see, plugin properties take a class name, followed by a -comma-separated list of values for the plugin's public fields or bean properties -in parentheses. OpenJPA will match each named property to a field or setter -method in the instantiated plugin instance, and set the field or invoke the -method with the given value (after converting the value to the right type, of -course). The first letter of the property names can be in either upper or lower -case. The following would also have been valid: - - -com.xyz.MyDataCache(cacheSize=1000, remoteHost=cacheserver) - - -If you do not need to pass any property settings to a plugin, you can just name -the class to use: - - -com.xyz.MyDataCache - - -Similarly, if the plugin has a default class that you do not want to change, you -can simply specify a list of property settings, without a class name. For -example, OpenJPA's query cache companion to the data cache has a default -implementation suitable to most users, but you still might want to change the -query cache's size. It has a CacheSize property for this -purpose: - - -CacheSize=1000 - - -Finally, many of OpenJPA's built-in options for plugins have short alias names -that you can use in place of the full class name. The data cache property, for -example, has an available alias of true for the standard -cache implementation. The property value simply becomes: - - -true - - -The standard cache implementation class also has a CacheSize -property, so to use the standard implementation and configure the size, specify: - - -true(CacheSize=1000) - - - -The remainder of this chapter reviews the set of configuration properties -OpenJPA recognizes. - -
-
- - OpenJPA Properties - - - - configuration - - - of OpenJPA properties - - - -OpenJPA defines many configuration properties. Most of these properties are -provided for advanced users who wish to customize OpenJPA's behavior; the -majority of developers can omit them. The following properties apply to any -OpenJPA back-end, though the given descriptions are tailored to OpenJPA's -default JDBC store. - - - -Few of the properties recognized by OpenJPA have been standardized in JPA 2.0 -Specification using equivalent names. These properties can be specified either -by the JPA standard key or equivalent OpenJPA key. Specifying the same key once -as JPA standard key and again as equivalent OpenJPA key in the same configuration, -however, is not allowed. The following table lists these standard JPA properties -and their OpenJPA equivalent. - - - - Standard JPA Properties and OpenJPA equivalents - - - - - - - Standard JPA 2.0 - OpenJPA Equivalent - - - - - javax.persistence.jdbc.driver - openjpa.ConnectionDriverName - - - javax.persistence.jdbc.url - openjpa.ConnectionURL - - - javax.persistence.jdbc.user - openjpa.ConnectionUserName - - - javax.persistence.jdbc.password - openjpa.ConnectionPassword - - - -
- - - - -
- - openjpa.AutoClear - - - - AutoClear - - - - - transactions - - - AutoClear - - - AutoClear - - - -Property name: openjpa.AutoClear - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getAutoClear - - - -Resource adaptor config-property: -AutoClear - - -Default: datastore - - -Possible values: datastore, -all - - -Description: When to automatically clear -instance state: on entering a datastore transaction, or on entering any -transaction. - -
-
- - openjpa.AutoDetach - - - - AutoDetach - - - - - detach - - - AutoDetach - - - AutoDetach - - - -Property name: openjpa.AutoDetach - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getAutoDetach - - - -Resource adaptor config-property: -AutoDetach - - -Default: - - - -Possible values: close, -commit, nontx-read - - -Description: A comma-separated list of events -when managed instances will be automatically detached. - -
-
- - openjpa.BrokerFactory - - - - BrokerFactory - - - -Property name: openjpa.BrokerFactory - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getBrokerFactory - - - -Resource adaptor config-property: -BrokerFactory - - -Default: jdbc - - -Possible values: jdbc, -abstractstore, remote - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.kernel.BrokerFactory type to -use. - -
-
- - openjpa.BrokerImpl - - - - BrokerImpl - - - - - Broker - - - BrokerImpl - - - -Property name: openjpa.BrokerImpl - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getBrokerImpl - - - -Resource adaptor config-property: -BrokerImpl - - -Default: default - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.kernel.Broker type to use at runtime. See - on for details. - -
- -
- openjpa.Callbacks - - Callbacks - - - Callbacks - Callbacks - - - Property name: openjpa.Callbacks - - - Configuration API: - - org.apache.openjpa.conf.OpenJPAConfiguration.getCallbackOptionsInstance - - - Resource adaptor config-property: Callbacks - - - Default: default - - - Description: A plugin string (see -) to fine tune some of the configurable -properties related to callbacks. The plug-in supports two boolean properties: - - - - PostPersistCallbackImmediate: whether the - post-persist callback is invoked as soon as a new instance - is managed. The default is false, implies that - the post-persist callback is invoked after the instance been committed - or flushed to the datastore. - - - - AllowsMultipleMethodsForSameCallback: whether - multiple methods of the same class can handle the same callback event. - Defaults to false. - - - -
- -
- - openjpa.ClassResolver - - - - ClassResolver - - - - - class loading - - - ClassResolver - - - -Property name: openjpa.ClassResolver - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getClassResolver - - - -Resource adaptor config-property: -ClassResolver - - -Default: default - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.util.ClassResolver implementation to use -for class name resolution. You may wish to plug in your own resolver if you have -special classloading needs. - -
-
- - openjpa.Compatibility - - - - Compatibility - - - - - backwards compatibility - - - -Property name: openjpa.Compatibility - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getCompatibility - - - -Resource adaptor config-property: -Compatibility - - -Default: - - - -Description: Encapsulates options to mimic the -behavior of previous OpenJPA releases. - -
-
- - openjpa.ConnectionDriverName - - - - ConnectionDriverName - - - - - connections - - - ConnectionDriverName - - - -Property name: -openjpa.ConnectionDriverName - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionDriverName - - - -Resource adaptor config-property: -ConnectionDriverName - - -Default: - - - -Description: The full class name of either the -JDBC java.sql.Driver, or a -javax.sql.DataSource implementation to use to connect to the -database. See for details. - -
-
- - openjpa.Connection2DriverName - - - - Connection2DriverName - - - - - connections - - - Connection2DriverName - - - -Property name: -openjpa.Connection2DriverName - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2DriverName - - - -Resource adaptor config-property: -Connection2DriverName - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionDriverName property described in -, but applies to the -alternate connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionFactory - - - - ConnectionFactory - - - - - connections - - - ConnectionFactory - - - -Property name: -openjpa.ConnectionFactory - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory - - - -Resource adaptor config-property: -ConnectionFactory - - -Default: - - - -Description: A javax.sql.DataSource - to use to connect to the database. See - for details. - -
-
- - openjpa.ConnectionFactory2 - - - - ConnectionFactory2 - - - - - connections - - - ConnectionFactory2 - - - -Property name: -openjpa.ConnectionFactory2 - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2 - - - -Resource adaptor config-property: -ConnectionFactory2 - - -Default: - - - -Description: An unmanaged -javax.sql.DataSource to use to connect to the database. See - for details. - -
-
- - openjpa.ConnectionFactoryName - - - - ConnectionFactoryName - - - - - connections - - - ConnectionFactoryName - - - -Property name: -openjpa.ConnectionFactoryName - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryName - - - -Resource adaptor config-property: -ConnectionFactoryName - - -Default: - - - -Description: The JNDI location of a -javax.sql.DataSource to use to connect to the database. See - for details. - -
-
- - openjpa.ConnectionFactory2Name - - - - ConnectionFactory2Name - - - - - connections - - - ConnectionFactory2Name - - - -Property name: -openjpa.ConnectionFactory2Name - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2Name - - - -Resource adaptor config-property: -ConnectionFactory2Name - - -Default: - - - -Description: The JNDI location of an unmanaged -javax.sql.DataSource to use to connect to the database. -See for details. - -
-
- - openjpa.ConnectionFactoryMode - - - - ConnectionFactoryMode - - - - - connections - - - ConnectionFactoryMode - - - -Property name: -openjpa.ConnectionFactoryMode - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryMode - - - -Resource adaptor config-property: -ConnectionFactoryMode - - -Default: local - - -Possible values: local, -managed - - -Description: The connection factory mode to use -when integrating with the application server's managed transactions. See - for details. - -
-
- - openjpa.ConnectionFactoryProperties - - - - ConnectionFactoryProperties - - - - - connections - - - ConnectionFactoryProperties - - - -Property name: -openjpa.ConnectionFactoryProperties - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryProperties - - - -Resource adaptor config-property: -ConnectionFactoryProperties - - -Default: - - - -Description: A plugin string (see -) listing properties for -configuration of the datasource in use. See the - for details. - -
-
- - openjpa.ConnectionFactory2Properties - - - - ConnectionFactory2Properties - - - - - connections - - - ConnectionFactory2Properties - - - -Property name: -openjpa.ConnectionFactory2Properties - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2Properties - - - -Resource adaptor config-property: -ConnectionFactory2Properties - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionFactoryProperties property described in -, but applies to the -alternate connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionPassword - - - - ConnectionPassword - - - - - connections - - - ConnectionPassword - - - -Property name: -openjpa.ConnectionPassword - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionPassword - - - -Resource adaptor config-property: -ConnectionPassword - - -Default: - - - -Description: The password for the user -specified in the ConnectionUserName property. See - for details. - -
-
- - openjpa.Connection2Password - - - - Connection2Password - - - - - connections - - - Connection2Password - - - -Property name: -openjpa.Connection2Password - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2Password - - - -Resource adaptor config-property: -Connection2Password - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionPassword property described in -, but applies to the -alternate connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionProperties - - - - ConnectionProperties - - - - - connections - - - ConnectionProperties - - - -Property name: -openjpa.ConnectionProperties - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionProperties - - - -Resource adaptor config-property: -ConnectionProperties - - -Default: - - - -Description: A plugin string (see -) listing properties to configure -the driver listed in the ConnectionDriverName property -described below. See for details. - -
-
- - openjpa.Connection2Properties - - - - Connection2Properties - - - - - connections - - - Connection2Properties - - - -Property name: -openjpa.Connection2Properties - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2Properties - - - -Resource adaptor config-property: -Connection2Properties - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionProperties property described in -, but applies to the -alternate connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionURL - - - - ConnectionURL - - - - - connections - - - ConnectionURL - - - -Property name: openjpa.ConnectionURL - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionURL - - - -Resource adaptor config-property: -ConnectionURL - - -Default: - - - -Description: The JDBC URL for the database. See - for details. - -
-
- - openjpa.Connection2URL - - - - Connection2URL - - - - - connections - - - Connection2URL - - - -Property name: openjpa.Connection2URL - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2URL - - - -Resource adaptor config-property: -Connection2URL - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionURL property described in -, but applies to the alternate -connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionUserName - - - - ConnectionUserName - - - - - connections - - - ConnectionUserName - - - -Property name: -openjpa.ConnectionUserName - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionUserName - - - -Resource adaptor config-property: -ConnectionUserName - - -Default: - - - -Description: The user name to use when -connecting to the database. See the -for details. - -
-
- - openjpa.Connection2UserName - - - - Connection2UserName - - - - - connections - - - Connection2UserName - - - -Property name: -openjpa.Connection2UserName - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2UserName - - - -Resource adaptor config-property: -Connection2UserName - - -Default: - - - -Description: This property is equivalent to the -openjpa.ConnectionUserName property described in -, but applies to the -alternate connection factory used for unmanaged connections. See - for details. - -
-
- - openjpa.ConnectionRetainMode - - - - ConnectionRetainMode - - - - - connections - - - ConnectionRetainMode - - - -Property name: -openjpa.ConnectionRetainMode - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionRetainMode - - - -Resource adaptor config-property: -ConnectionRetainMode - - -Default: on-demand - - -Description: Controls how OpenJPA uses -datastore connections. This property can also be specified for individual -sessions. See for details. - -
-
- - openjpa.DataCache - - - - DataCache - - - - - caching - - - DataCache - - - -Property name: openjpa.DataCache - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getDataCache - - - -Resource adaptor config-property: -DataCache - - -Default: false - - -Description: A plugin list string (see -) describing the - -org.apache.openjpa.datacache.DataCaches to use for data -caching. See for details. - -
-
- - openjpa.DataCacheManager - - - - DataCacheManager - - - - - caching - - - DataCacheManager - - - -Property name: -openjpa.DataCacheManager - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getDataCacheManager - - - -Resource adaptor config-property: -DataCacheManager - - -Default: default - - -Description: A plugin string (see -) describing the - -openjpa.datacache.DataCacheManager that manages -the system data caches. See for details -on data caching. - -
-
- - openjpa.DataCacheTimeout - - - - DataCacheTimeout - - - - - caching - - - DataCacheTimeout - - - -Property name: -openjpa.DataCacheTimeout - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getDataCacheTimeout - - - -Resource adaptor config-property: -DataCacheTimeout - - -Default: -1 - - -Description: The number of milliseconds that -data in the data cache is valid. Set this to -1 to indicate that data should not -expire from the cache. This property can also be specified for individual -classes. See for details. - -
-
- - openjpa.DetachState - - - - DetachState - - - - - detach - - - DetachState - - - DetachState - - - -Property name: openjpa.DetachState - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getDetachState - - - -Resource adaptor config-property: -DetachState - - -Default: loaded - - -Possible values: loaded, -fetch-groups, all - - -Description: Determines which fields are part -of the detached graph and related options. For more details, see -. - -
-
- - openjpa.DynamicDataStructs - - - - DynamicDataStructs - - - - - caching - - - DynamicDataStructs - - - - - remote - - - DynamicDataStructs - - - -Property name: -openjpa.DynamicDataStructs - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getDynamicDataStructs - - - -Resource adaptor config-property: -DynamicDataStructs - - -Default: false - - -Description: Whether to dynamically generate -customized structs to hold persistent data. Both the OpenJPA data cache and the -remote framework rely on data structs to cache and transfer persistent state. -With dynamic structs, OpenJPA can customize data storage for each class, -eliminating the need to generate primitive wrapper objects. This saves memory -and speeds up certain runtime operations. The price is a longer warm-up time for -the application - generating and loading custom classes into the JVM takes time. -Therefore, only set this property to true if you have a -long-running application where the initial cost of class generation is offset by -memory and speed optimization over time. - -
-
- - openjpa.FetchBatchSize - - - - FetchBatchSize - - - - - large result sets - - - FetchBatchSize - - - -Property name: openjpa.FetchBatchSize - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getFetchBatchSize - - - -Resource adaptor config-property: -FetchBatchSize - - -Default: -1 - - -Description: The number of rows to fetch at -once when scrolling through a result set. The fetch size can also be set at -runtime. See for details. - -
-
- - openjpa.FetchGroups - - - - fetch groups - - - FetchGroups - - - -Property name: openjpa.FetchGroups - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getFetchGroups - - - -Resource adaptor config-property: -FetchGroups - - -Default: - - - -Description: A comma-separated list of fetch -group names that are to be loaded when retrieving objects from the datastore. -Fetch groups can also be set at runtime. See - for details. - -
- -
- - openjpa.FlushBeforeQueries - - - - FlushBeforeQueries - - - - - Query - - - FlushBeforeQueries - - - - - flush - - - FlushBeforeQueries - - - -Property name: -openjpa.FlushBeforeQueries - - -Property name: -openjpa.FlushBeforeQueries - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getFlushBeforeQueries - - - -Resource adaptor config-property: -FlushBeforeQueries - - -Default: true - - -Description: Whether or not to flush any -changes made in the current transaction to the datastore before executing a -query. See for details. - -
-
- - openjpa.IgnoreChanges - - - - IgnoreChanges - - - -Property name: openjpa.IgnoreChanges - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getIgnoreChanges - - - -Resource adaptor config-property: -IgnoreChanges - - -Default: false - - -Description: Whether to consider modifications -to persistent objects made in the current transaction when evaluating queries. -Setting this to true allows OpenJPA to ignore changes and -execute the query directly against the datastore. A value of false - forces OpenJPA to consider whether the changes in the current -transaction affect the query, and if so to either evaluate the query in-memory -or flush before running it against the datastore. - -
-
- openjpa.Id - - Id - - - Property name: - openjpa.Id - - - Resource adaptor config-property: - Id - - - Default: none - - - Description: An - environment-specific identifier for this configuration. This - might correspond to a JPA persistence-unit name, or to some other - more-unique value available in the current environment. - -
- -InitializeEagerly -
- - openjpa.InitializeEagerly - - - - InverseManager - - - - - Initialization - - - Configuration - - - -Property name: openjpa.InitializeEagerly - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.isInitializeEagerly - - - -Resource adaptor config-property: -InitializeEagerly - - -Default: false - - -Possible values: false, -true - - -Description: Controls whether initialization -is eager or lazy. Eager initialization imply all persistent classes, their -mapping information, database connectivity and all other resources specified in -the configuration of a persistence unit will be initialized when a persistent -unit is constructed. The default behavior is -lazy i.e. persistent classes, database and other resources are initialized only -when the application refers to a resource for the first time. - -
- - - -
- - openjpa.InverseManager - - - - InverseManager - - - - - bidirectional relation - - - InverseManager - - - -Property name: openjpa.InverseManager - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getInverseManager - - - -Resource adaptor config-property: -InverseManager - - -Default: false - - -Possible values: false, -true - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.kernel.InverseManager to use -for managing bidirectional relations upon a flush. See - for usage documentation. - -
-
- - openjpa.LockManager - - - - LockManager - - - - - locking - - - LockManager - - - -Property name: openjpa.LockManager - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getLockManager - - - -Resource adaptor config-property: -LockManager - - -Default: mixed - - -Possible values: none, -sjvm, version, -pessimistic, mixed - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.kernel.LockManager to use for acquiring -locks on persistent instances during transactions. See - for more information. - -
-
- - openjpa.LockTimeout - - - - LockTimeout - - - - - locking - - - LockTimeout - - - -Property name: openjpa.LockTimeout - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getLockTimeout - - - -Resource adaptor config-property: -LockTimeout - - -Default: -1 - - -Description: The number of milliseconds to wait -for an object lock before throwing an exception, or -1 for no limit. See - for details. - -
-
- - openjpa.Log - - - - Log - - - - - logging - - - Log - - - -Property name: openjpa.Log - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getLog - - - -Resource adaptor config-property: Log - - - -Default: true - - -Possible values: openjpa, -commons, log4j, none - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.lib.log.LogFactory to use for logging. -For details on logging, see . - -
-
- - openjpa.ManagedRuntime - - - - ManagedRuntime - - - - - transactions - - - managed - - - ManagedRuntime - - - -Property name: openjpa.ManagedRuntime - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getManagedRuntime - - - -Resource adaptor config-property: -ManagedRuntime - - -Default: auto - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.ee.ManagedRuntime implementation to use -for obtaining a reference to the TransactionManager in an -enterprise environment. - -
-
- - openjpa.Mapping - - - - Mapping - - - -Property name: openjpa.Mapping - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getMapping - - - -Resource adaptor config-property: -Mapping - - -Default: - - - -Description: The symbolic name of the -object-to-datastore mapping to use. - -
-
- - openjpa.MaxFetchDepth - - - - MaxFetchDepth - - - - - eager fetching - - - MaxFetchDepth - - - -Property name: openjpa.MaxFetchDepth - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getMaxFetchDepth - - - -Resource adaptor config-property: -MaxFetchDepth - - -Default: -1 - - -Description: The maximum depth of relations to -traverse when eager fetching. Use -1 for no limit. Defaults to no limit. See - for details on eager fetching. - -
-
- - openjpa.MetaDataFactory - - - - MetaDataFactory - - - - - metadata - - - MetaDataFactory - - - -Property name: openjpa.MetaDataFactory - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getMetaDataFactory - - - -Resource adaptor config-property: -MetaDataFactory - - -Default: jpa - - -Description: A plugin string (see -) describing the - -openjpa.meta.MetaDataFactory to use to store and -retrieve metadata for your persistent classes. See - for details. - -
-
- - openjpa.Multithreaded - - - - Multithreaded - - - - - threading - - - Multithreaded - - - -Property name: openjpa.Multithreaded - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getMultithreaded - - - -Resource adaptor config-property: -Multithreaded - - -Default: false - - -Description: Whether persistent instances and -OpenJPA components other than the EntityManagerFactory -will be accessed by multiple threads at once. - -
-
- - openjpa.Optimistic - - - - Optimistic - - - - - transactions - - - optimistic - - - -Property name: openjpa.Optimistic - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getOptimistic - - - -Resource adaptor config-property: -Optimistic - - -Default: true - - -Description: Selects between optimistic and -pessimistic (datastore) transactional modes. - -
-
- - openjpa.OrphanedKeyAction - - - - OrphanedKeyAction - - - - - foreign keys - - - OrphanedKeyAction - - - -Property name: -openjpa.OrphanedKeyAction - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getOrphanedKeyAction - - - -Resource adaptor config-property: -OrphanedKeyAction - - -Default: log - - -Possible values: log, -exception, none - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.event.OrphanedKeyAction to -invoke when OpenJPA discovers an orphaned datastore key. See - for details. - -
-
- - openjpa.NontransactionalRead - - - - NontransactionalRead - - - -Property name: -openjpa.NontransactionalRead - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getNontransactionalRead - - - -Resource adaptor config-property: -NontransactionalRead - - -Default: true - - -Description: Whether the OpenJPA runtime will -allow you to read data outside of a transaction. - -
-
- - openjpa.NontransactionalWrite - - - - NontransactionalWrite - - - -Property name: -openjpa.NontransactionalWrite - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getNontransactionalWrite - - - -Resource adaptor config-property: -NontransactionalWrite - - -Default: true - - -Description: Whether you can modify persistent -objects and perform persistence operations outside of a transaction. Changes -will take effect on the next transaction. - -
-
- - openjpa.ProxyManager - - - - ProxyManager - - - - - proxies - - - ProxyManager - - - -Property name: openjpa.ProxyManager - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getProxyManager - - - -Resource adaptor config-property: -ProxyManager - - -Default: default - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.util.ProxyManager to use for proxying -mutable second class objects. See - for details. - -
-
- - openjpa.QueryCache - - - - QueryCache - - - - - caching - - - QueryCache - - - -Property name: openjpa.QueryCache - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getQueryCache - - - -Resource adaptor config-property: -QueryCache - - -Default: true, when the data -cache (see ) is also enabled, -false otherwise. - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.datacache.QueryCache -implementation to use for caching of queries loaded from the data store. See - for details. - -
-
- - openjpa.QueryCompilationCache - - - - QueryCompilationCache - - - - - caching - - - QueryCompilationCache - - - -Property name: -openjpa.QueryCompilationCache - - -Resource adaptor config-property: -QueryCompilationCache - - -Default: true. - - -Description: A plugin string (see -) describing the -java.util.Map to use for caching of data used during -query compilation. See for details. - -
-
- - openjpa.ReadLockLevel - - - - ReadLockLevel - - - - - locking - - - ReadLockLevel - - - -Property name: openjpa.ReadLockLevel - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getReadLockLevel - - - -Resource adaptor config-property: -ReadLockLevel - - -Default: read - - -Possible values: none, -read, write, -optimistic, optimistic-force-increment, -pessimistic-read, pessimistic-write, -pessimistic-force-increment, numeric values for -lock-manager specific lock levels - - -Description: The default level at which to lock -objects retrieved during a non-optimistic transaction. Note that for the default -JDBC lock manager, read and write lock -levels are equivalent. Lock levels pessimistic-read, -pessimistic-write and -pessimistic-force-increment are in effect only when the -mixed lock manager is used. - -
-
- - openjpa.RemoteCommitProvider - - - - RemoteCommitProvider - - - - - caching - - - RemoteCommitProvider - - - - - remote - - - RemoteCommitProvider - - - -Property name: -openjpa.RemoteCommitProvider - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getRemoteCommitProvider - - - -Resource adaptor config-property: -RemoteCommitProvider - - -Default: - - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.event.RemoteCommitProvider -implementation to use for distributed event notification. See - for more information. - -
-
- - openjpa.RestoreState - - - - RestoreState - - - -Property name: openjpa.RestoreState - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getRestoreState - - - -Resource adaptor config-property: -RestoreState - - -Default: none - - -Possible values: none, -immutable, all - - -Description: Whether to restore managed fields -to their pre-transaction values when a rollback occurs. - -
-
- - openjpa.RetainState - - - - RetainState - - - -Property name: openjpa.RetainState - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getRetainState - - - -Resource adaptor config-property: -RetainState - - -Default: true - - -Description: Whether persistent fields retain -their values on transaction commit. - -
-
- - openjpa.RetryClassRegistration - - - - RetryClassRegistration - - - - - metadata - - - RetryClassRegistration - - - -Property name: -openjpa.RetryClassRegistration - - -Configuration API: - - -org.apache.openjpa.conf.OpenJPAConfiguration.getRetryClassRegistration - - - -Resource adaptor config-property: -RetryClassRegistration - - -Default: false - - -Description: Controls whether to log a warning -and defer registration instead of throwing an exception when a persistent class -cannot be fully processed. This property should only be -used in complex classloader situations where security is preventing OpenJPA from -reading registered classes. Setting this to true unnecessarily may obscure more -serious problems. - -
-
- openjpa.RuntimeUnenhancedClasses - - Property name: - openjpa.RuntimeUnenhancedClasses - - - Configuration API: - org.apache.openjpa.conf.OpenJPAConfiguration.getRuntimeUnenhancedClasses - - - Resource adaptor config property: - RuntimeUnenhancedClasses - - - Default: - supported - - - - Possible values: - supported, - unsupported, - warn - - - Description: - The RuntimeUnenhancedClasses property controls how OpenJPA - handles classes that have not been enhanced by the PCEnhancer - tool or automatically by a javaagent. If RuntimeUnenhancedClasses is - set to supported OpenJPA will automatically - create subclasses for unenhanced entity classes. If set to - unsupported OpenJPA will not create subclasses - for unenhanced entity classes and will throw an exception when - they are detected. If set to warn OpenJPA - will not create subclasses for unenhanced entity classes - but will log a warning message. - - - See the reference guide section on unenhanced types for more - information - - -
-
- - openjpa.SavepointManager - - -Property name: -openjpa.SavepointManager - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getSavepointManager - - -Resource adaptor config-property: -SavepointManager - - -Default: in-mem - - -Possible values: in-mem, -jdbc, oracle - - -Description: A plugin string (see -) describing a - -org.apache.openjpa.kernel.SavepointManager to -use for managing transaction savepoints. See - for details. - -
-
- - openjpa.Sequence - - - - Sequence - - - -Property name: openjpa.Sequence - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getSequence - - - -Resource adaptor config-property: -Sequence - - -Default: table - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.kernel.Seq implementation to use for the -system sequence. See for more -information. - -
-
- - openjpa.Specification - - - - Specification - - - -Property name: openjpa.Specification - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getSpecificationInstance - - - -Resource adaptor config-property: -Specification - - -Default: table - - -Description: A formatted string describing the Specification -to use for the default configuration options. The format of the Specifcation string is -name [major.[minor]] where name denotes the name of the -Specification such as JPA or JDO, major -denotes the major integral version number of the Specification and minor -denotes a minor version which can be an arbitrary string. -See for more information. - -
- -
- - openjpa.TransactionMode - - - - TransactionMode - - - - - transactions - - - TransactionMode - - - -Property name: openjpa.TransactionMode - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getTransactionMode - - - -Resource adaptor config-property: -TransactionMode - - -Default: local - - -Possible values: local, -managed - - -Description: The default transaction mode to -use. You can override this setting per-session. - -
-
- - openjpa.WriteLockLevel - - - - WriteLockLevel - - - - - locking - - - WriteLockLevel - - - -Property name: openjpa.WriteLockLevel - - - -Configuration API: - -org.apache.openjpa.conf.OpenJPAConfiguration.getWriteLockLevel - - - -Resource adaptor config-property: -WriteLockLevel - - -Default: write - - -Possible values: none, -read, write, -optimistic, optimistic-force-increment, -pessimistic-read, pessimistic-write, -pessimistic-force-increment, numeric values for -lock-manager specific lock levels. - - -Description: The default level at which to lock -objects changed during a non-optimistic transaction. Note that for the default -JDBC lock manager, read and write lock -levels are equivalent. Lock levels pessimistic-read, -pessimistic-write and -pessimistic-force-increment are in effect only when the -mixed lock manager is used. - -
-
-
- - OpenJPA JDBC Properties - - - - configuration - - - of JDBC properties - - - -The following properties apply exclusively to the OpenJPA JDBC back-end. - -
- - openjpa.jdbc.ConnectionDecorators - - - - ConnectionDecorators - - - - - connections - - - ConnectionDecorators - - - -Property name: -openjpa.jdbc.ConnectionDecorators - - -Configuration API: - - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getConnectionDecorators - - - -Resource adaptor config-property: -ConnectionDecorators - - -Default: - - - -Description: A comma-separated list of plugin -strings (see ) describing - -org.apache.openjpa.lib.jdbc.ConnectionDecorator -instances to install on the connection factory. These decorators can wrap -connections passed from the underlying DataSource to add -functionality. OpenJPA will pass all connections through the list of decorators -before using them. Note that by default OpenJPA employs all -of the built-in decorators in the org.apache.openjpa.lib.jdbc - package already; you do not need to list them here. - -
-
- - openjpa.jdbc.DBDictionary - - - - DBDictionary - - - - - JDBC - - - DBDictionary - - - -Property name: -openjpa.jdbc.DBDictionary - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getDBDictionary - - - -Resource adaptor config-property: -DBDictionary - - -Default: Based on the -openjpa.ConnectionURL - -openjpa.ConnectionDriverName - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.jdbc.sql.DBDictionary to use -for database interaction. OpenJPA typically auto-configures the dictionary based -on the JDBC URL, but you may have to set this property explicitly if you are -using an unrecognized driver, or to plug in your own dictionary for a database -OpenJPA does not support out-of-the-box. See - for details. - -
-
- - openjpa.jdbc.DriverDataSource - - - - DriverDataSource - - - - - JDBC - - - DriverDataSource - - - -Property name: -openjpa.jdbc.DriverDataSource - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getDriverDataSource - - - -Resource adaptor config-property: -DriverDataSource - - -Default: pooling - - -Description: The alias or full class name of -the - -org.apache.openjpa.jdbc.schema.DriverDataSource -implementation to use to wrap JDBC Driver classes with javax.sql.DataSource -instances. - -
-
- - openjpa.jdbc.EagerFetchMode - - - - EagerFetchMode - - - - - eager fetching - - - EagerFetchMode - - - -Property name: -openjpa.jdbc.EagerFetchMode - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getEagerFetchMode - - - -Resource adaptor config-property: -EagerFetchMode - - -Default: parallel - - -Possible values: parallel, -join, none - - -Description: Optimizes how OpenJPA loads -persistent relations. This setting can also be varied at runtime. See - for details. - -
-
- - openjpa.jdbc.FetchDirection - - - - FetchDirection - - - - - large result sets - - - FetchDirection - - - -Property name: -openjpa.jdbc.FetchDirection - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getFetchDirection - - - -Resource adaptor config-property: -FetchDirection - - -Default: forward - - -Possible values: forward, -reverse, unknown - - -Description: The expected order in which query -result lists will be accessed. This property can also be varied at runtime. See - for details. - -
-
- - openjpa.jdbc.JDBCListeners - - - - JDBCListeners - - - - - JDBC - - - JDBCListeners - - - -Property name: -openjpa.jdbc.JDBCListeners - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getJDBCListeners - - - -Resource adaptor config-property: -JDBCListeners - - -Default: - - - -Description: A comma-separated list of plugin -strings (see ) describing - -org.apache.openjpa.lib.jdbc.JDBCListener event -listeners to install. These listeners will be notified on various JDBC-related -events. - -
-
- - openjpa.jdbc.LRSSize - - - - LRSSize - - - - - large result sets - - - LRSSize - - - -Property name: openjpa.jdbc.LRSSize - - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getLRSSize - - - -Resource adaptor config-property: -LRSSize - - -Default: query - - -Possible values: query, -last, unknown - - -Description: The strategy to use to calculate -the size of a result list. This property can also be varied at runtime. See - for details. - -
-
- - openjpa.jdbc.MappingDefaults - - - - MappingDefaults - - - - - mapping metadata - - - MappingDefaults - - - -Property name: -openjpa.jdbc.MappingDefaults - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getMappingDefaults - - - -Resource adaptor config-property: -MappingDefaults - - -Default: jpa - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.jdbc.meta.MappingDefaults to -use to define default column names, table names, and constraints for your -persistent classes. See for -details. - -
-
- - openjpa.jdbc.MappingFactory - - - - MappingFactory - - - - - mapping metadata - - - MappingFactory - - - -Property name: -openjpa.jdbc.MappingFactory - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getMappingFactory - - - -Resource adaptor config-property: -MappingFactory - - -Default: - - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.meta.MetaDataFactory to use to -store and retrieve object-relational mapping information for your persistent -classes. See for details. - - -
-
- - openjpa.jdbc.QuerySQLCache - - - - Prepared SQL Cache - - - - - caching - - - QuerySQLCache - - - -Property name: -openjpa.jdbc.QuerySQLCache - - -Resource adaptor config-property: -QuerySQLCache - - -Default: true. - - -Description: A plugin string (see -) describing the options to cache and -reuse SQL statements generated for JPQL queries. -See for details. - -
-
- - openjpa.jdbc.ResultSetType - - - - ResultSetType - - - - - large result sets - - - ResultSetType - - - -Property name: -openjpa.jdbc.ResultSetType - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getResultSetType - - - -Resource adaptor config-property: -ResultSetType - - -Default: forward-only - - -Possible values: forward-only -, scroll-sensitive, scroll-insensitive - - -Description: The JDBC result set type to use -when fetching result lists. This property can also be varied at runtime. See - for details. - -
-
- - openjpa.jdbc.Schema - - - - schema - - - Schema - - - -Property name: openjpa.jdbc.Schema - - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchema - - - -Resource adaptor config-property: -Schema - - -Default: - - - -Description: The default schema name to prepend -to unqualified table names. Also, the schema in which OpenJPA will create new -tables. See for details. - -
-
- - openjpa.jdbc.SchemaFactory - - - - SchemaFactory - - - - - schema - - - SchemaFactory - - - -Property name: -openjpa.jdbc.SchemaFactory - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchemaFactory - - - -Resource adaptor config-property: -SchemaFactory - - -Default: dynamic - - -Possible values: dynamic, -native, file, table, -others - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.jdbc.schema.SchemaFactory to -use to store and retrieve information about the database schema. See - for details. - -
-
- - openjpa.jdbc.Schemas - - - - schema - - - Schemas - - - -Property name: openjpa.jdbc.Schemas - - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchemas - - - -Resource adaptor config-property: -Schemas - - -Default: - - - -Description: A comma-separated list of the -schemas and/or tables used for your persistent data. See - for details. - -
-
- - openjpa.jdbc.SQLFactory - - - - SQLFactory - - - - - SQL - - - SQLFactory - - - -Property name: openjpa.jdbc.SQLFactory - - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSQLFactory - - - -Resource adaptor config-property: -SQLFactory - - -Default: default - - -Description: A plugin string (see -) describing the - -org.apache.openjpa.jdbc.sql.SQLFactory to use to abstract -common SQL constructs. - -
-
- - openjpa.jdbc.SubclassFetchMode - - - - SubclassFetchMode - - - - - eager fetching - - - SubclassFetchMode - - - - - inheritance - - - SubclassFetchMode - - - -Property name: -openjpa.jdbc.SubclassFetchMode - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSubclassFetchMode - - - -Resource adaptor config-property: -SubclassFetchMode - - -Default: parallel - - -Possible values: parallel, -join, none - - -Description: How to select subclass data when -it is in other tables. This setting can also be varied at runtime. See -. - -
-
- - openjpa.jdbc.SynchronizeMappings - - - - SynchronizeMappings - - - - - mapping metadata - - - SynchronizeMappings - - - -Property name: -openjpa.jdbc.SynchronizeMappings - - -Configuration API: - - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSynchronizeMappings - - - -Resource adaptor config-property: -SynchronizeMappings - - -Default: - - - -Description: Controls whether OpenJPA will -attempt to run the mapping tool on all persistent classes to synchronize their -mappings and schema at runtime. Useful for rapid test/debug cycles. See - for more information. - -
-
- - openjpa.jdbc.TransactionIsolation - - - - TransactionIsolation - - - - - transactions - - - TransactionIsolation - - - - - JDBC - - - TransactionIsolation - - - -Property name: -openjpa.jdbc.TransactionIsolation - - -Configuration API: - - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getTransactionIsolation - - - -Resource adaptor config-property: -TransactionIsolation - - -Default: default - - -Possible values: default, -none, read-committed, -read-uncommitted, repeatable-read, -serializable - - -Description: The JDBC transaction isolation -level to use. See for -details. - -
-
- - openjpa.jdbc.UpdateManager - - - - UpdateManager - - - - - JDBC - - - UpdateManager - - - -Property name: -openjpa.jdbc.UpdateManager - - -Configuration API: - -org.apache.openjpa.jdbc.conf.JDBCConfiguration.getUpdateManager - - - -Resource adaptor config-property: -UpdateManager - - -Default: batching-constraint - - - Possible values: default, -operation-order, constraint, -batching-constraint, batching-operation-order - - -Description: The full class name of the - -org.apache.openjpa.jdbc.kernel.UpdateManager to -use to flush persistent object changes to the datastore. The provided default -implementation is - -org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager -. - - -
- -
- Compatibility with Specification - -The default behavior of certain OpenJPA API methods can evolve to align with the behaviors -defined in JPA specification. To maintain backward compatibility, OpenJPA allows configuration -options such that while the default behavior changes to align with current JPA Specification, the -previous behaviors can always be emulated. - - -For example, JPA 2.0 specification -introduces a new API void EntityManager.detach(Object entity) that detaches -the given entity from the current persistence context. OpenJPA has provided similar -feature via <T> T OpenJPAEntityManager.detach(T entity) prior to JPA 2.0. -OpenJPA detach(), however, has different default behavior than what JPA 2.0 -specification mandates. Firstly, OpenJPA creates a copy of the given entity as a detached instance -and returns it, whereas JPA 2.0 behavior requires the same given entity instance be detached. -Secondly, the given instance is removed from the persistence context for JPA 2.0, whereas -OpenJPA detach() method, prior to JPA 2.0, does not remove the instance -from the persistence context as a copy is returned. Thirdly, OpenJPA will flush before -detaching a dirty instance so that the detached instance can later be merged, whereas -JPA 2.0 detach() semantics does not require a dirty instance be flushed -before detach. - - -A user application running with OpenJPA that is compliant to a specific version of JPA of specification, -the older behavior can be emulated by configuring OpenJPA Compatibility options. -For example, openjpa.Compatibility=FlushBeforeDetach=false,CopyOnDetach=true -will emulate the older behavior of detach even when running with OpenJPA that are -compliant to JPA 2.0 Specification. The configuration can also be set to a different version of the specification. -For example, openjpa.Specification="JPA 1.0" configuration setting will emulate -default OpenJPA behavior as it were for JPA Specification version 1.0. Setting via -openjpa.Specification is a shorthand for more fine-grained control available via -openjpa.Compatibility. - - -
-
- + + + + + Configuration + + + + configuration + + +
+ + Introduction + + +This chapter describes the OpenJPA configuration framework. It concludes with +descriptions of all the configuration properties recognized by OpenJPA. You may +want to browse these properties now, but it is not necessary. Most of them will +be referenced later in the documentation as we explain the various features they +apply to. + +
+
+ + Runtime Configuration + + + + configuration + + + runtime + + + +The OpenJPA runtime includes a comprehensive system of configuration defaults +and overrides: + + + + + + + openjpa.xml + + +OpenJPA first looks for an optional openjpa.xml resource. +OpenJPA searches for this resource in each top-level directory of your +CLASSPATH. OpenJPA will also find the resource if you place it within +a META-INF directory in any top-level directory of the +CLASSPATH. The openjpa.xml resource +contains property settings in +JPA's XML format. + + + + +You can customize the name or location of the above resource by specifying the +correct resource path in the openjpa.properties System +property. + + + + +You can override any value defined in the above resource by setting the System +property of the same name to the desired value. + + + + + + + Persistence + + + createEntityManagerFactory + + +In JPA, the values in the standard META-INF/persistence.xml + bootstrapping file used by the +Persistence + class at runtime override the values in the above resource, as well as +any System property settings. The Map passed to +Persistence.createEntityManagerFactory at runtime also +overrides previous settings, including properties defined in +persistence.xml. + + + + +In JPA, The Map passed to the methods defined in the +Query and EntityManager interfaces +at runtime also overrides previous settings, including properties defined in +persistence.xml. The Map is in +effect only during the method invocation. + + + + +When using JCA deployment the config-property values in your +ra.xml file override other settings. + + + + +All OpenJPA command-line tools accept flags that allow you to specify the +configuration resource to use, and to override any property. + describes these flags. + + + + + +Internally, the OpenJPA runtime environment and development +tools manipulate property settings through a general + +Configuration interface, and in particular its + +OpenJPAConfiguration and + +JDBCConfiguration subclasses. For advanced +customization, OpenJPA's extended runtime interfaces and its development tools +allow you to access these interfaces directly. See the +Javadoc for details. + + +
+
+ + Command Line Configuration + + + + configuration + + + command line + + + +OpenJPA development tools share the same set of configuration defaults and +overrides as the runtime system. They also allow you to specify property values +on the command line: + + + + +-properties/-p <configuration file or resource>: Use +the -properties flag, or its shorter -p +form, to specify a configuration file to use. Note that OpenJPA always searches +the default file locations described above, so this flag is only needed when you +do not have a default resource in place, or when you wish to override the +defaults. The given value can be the path to a file, or the resource name of a +file somewhere in the CLASSPATH. OpenJPA will search the +given location as well as the location prefixed by META-INF/ +. Thus, to point an OpenJPA tool at +META-INF/my-persistence.xml, you can use: + + +<tool> -p my-persistence.xml + + +If you want to run a tool against just one particular persistence unit in +a configuration file, you can do so by specifying an anchor along with the +resource. If you do not specify an anchor, the tools will run against all +the persistence units defined within the specified resource, or the default +resource if none is specified. If the persistence unit is defined within +the default resource location, then you can just specify the raw anchor itself: + + +<tool> -p my-persistence.xml#sales-persistence-unit +<tool> -p #invoice-persistence-unit + + + + +-<property name> <property value>: Any +configuration property that you can specify in a configuration file can be +overridden with a command line flag. The flag name is always the last token of +the corresponding property name, with the first letter in either upper or lower +case. For example, to override the openjpa.ConnectionUserName +property, you could pass the -connectionUserName <value> + flag to any tool. Values set this way override both the values in the +configuration file and values set via System properties. + + + +
+ + Code Formatting + + + + code formatting + + + +Some OpenJPA development tools generate Java code. These tools share a common +set of command-line flags for formatting their output to match your coding +style. All code formatting flags can begin with either the codeFormat + or cf prefix. + + + + +-codeFormat./-cf.tabSpaces <spaces>: The number of +spaces that make up a tab, or 0 to use tab characters. Defaults to using tab +characters. + + + + +-codeFormat./-cf.spaceBeforeParen <true/t | false/f>: +Whether or not to place a space before opening parentheses on method calls, if +statements, loops, etc. Defaults to false. + + + + +-codeFormat./-cf.spaceInParen <true/t | false/f>: +Whether or not to place a space within parentheses; i.e. method( arg) +. Defaults to false. + + + + +-codeFormat./-cf.braceOnSameLine <true/t | false/f>: +Whether or not to place opening braces on the same line as the declaration that +begins the code block, or on the next line. Defaults to true +. + + + + +-codeFormat./-cf.braceAtSameTabLevel <true/t | false/f> +: When the braceOnSameLine option is disabled, you can choose +whether to place the brace at the same tab level of the contained code. Defaults +to false. + + + + +-codeFormat./-cf.scoreBeforeFieldName <true/t | false/f> +: Whether to prefix an underscore to names of private member +variables. Defaults to false. + + + + +-codeFormat./-cf.linesBetweenSections <lines>: The +number of lines to skip between sections of code. Defaults to 1. + + + + + + Code Formatting with the Application Id Tool + + +java org.apache.openjpa.enhance.ApplicationIdTool -cf.spaceBeforeParen true -cf.tabSpaces 4 + + +
+
+
+ + Plugin Configuration + + + + configuration + + + plugins + + + + + plugins + + + configuration + + + +Because OpenJPA is a highly customizable environment, many configuration +properties relate to the creation and configuration of system plugins. Plugin +properties have a syntax very similar to that of Java 5 annotations. They allow +you to specify both what class to use for the plugin and how to configure the +public fields or bean properties of the instantiated plugin instance. The +easiest way to describe the plugin syntax is by example: + + +OpenJPA has a pluggable L2 caching mechanism that is controlled by the +openjpa.DataCache configuration property. Suppose that you have +created a new class, com.xyz.MyDataCache, that you want +OpenJPA to use for caching. You've made instances of MyDataCache + configurable via two methods, setCacheSize(int size) + and setRemoteHost(String host). The +sample below shows how you would tell OpenJPA to use an instance of your custom +plugin with a max size of 1000 and a remote host of cacheserver +. + + +<property name="openjpa.DataCache" + value="com.xyz.MyDataCache(CacheSize=1000, RemoteHost=cacheserver)"/> + + +As you can see, plugin properties take a class name, followed by a +comma-separated list of values for the plugin's public fields or bean properties +in parentheses. OpenJPA will match each named property to a field or setter +method in the instantiated plugin instance, and set the field or invoke the +method with the given value (after converting the value to the right type, of +course). The first letter of the property names can be in either upper or lower +case. The following would also have been valid: + + +com.xyz.MyDataCache(cacheSize=1000, remoteHost=cacheserver) + + +If you do not need to pass any property settings to a plugin, you can just name +the class to use: + + +com.xyz.MyDataCache + + +Similarly, if the plugin has a default class that you do not want to change, you +can simply specify a list of property settings, without a class name. For +example, OpenJPA's query cache companion to the data cache has a default +implementation suitable to most users, but you still might want to change the +query cache's size. It has a CacheSize property for this +purpose: + + +CacheSize=1000 + + +Finally, many of OpenJPA's built-in options for plugins have short alias names +that you can use in place of the full class name. The data cache property, for +example, has an available alias of true for the standard +cache implementation. The property value simply becomes: + + +true + + +The standard cache implementation class also has a CacheSize +property, so to use the standard implementation and configure the size, specify: + + +true(CacheSize=1000) + + + +The remainder of this chapter reviews the set of configuration properties +OpenJPA recognizes. + +
+
+ + OpenJPA Properties + + + + configuration + + + of OpenJPA properties + + + +OpenJPA defines many configuration properties. Most of these properties are +provided for advanced users who wish to customize OpenJPA's behavior; the +majority of developers can omit them. The following properties apply to any +OpenJPA back-end, though the given descriptions are tailored to OpenJPA's +default JDBC store. + + + +Few of the properties recognized by OpenJPA have been standardized in JPA 2.0 +Specification using equivalent names. These properties can be specified either +by the JPA standard key or equivalent OpenJPA key. Specifying the same key once +as JPA standard key and again as equivalent OpenJPA key in the same configuration, +however, is not allowed. The following table lists these standard JPA properties +and their OpenJPA equivalent. + + + + Standard JPA Properties and OpenJPA equivalents + + + + + + + Standard JPA 2.0 + OpenJPA Equivalent + + + + + javax.persistence.jdbc.driver + openjpa.ConnectionDriverName + + + javax.persistence.jdbc.url + openjpa.ConnectionURL + + + javax.persistence.jdbc.user + openjpa.ConnectionUserName + + + javax.persistence.jdbc.password + openjpa.ConnectionPassword + + + +
+ + + + +
+ + openjpa.AutoClear + + + + AutoClear + + + + + transactions + + + AutoClear + + + AutoClear + + + +Property name: openjpa.AutoClear + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getAutoClear + + + +Resource adaptor config-property: +AutoClear + + +Default: datastore + + +Possible values: datastore, +all + + +Description: When to automatically clear +instance state: on entering a datastore transaction, or on entering any +transaction. + +
+
+ + openjpa.AutoDetach + + + + AutoDetach + + + + + detach + + + AutoDetach + + + AutoDetach + + + +Property name: openjpa.AutoDetach + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getAutoDetach + + + +Resource adaptor config-property: +AutoDetach + + +Default: - + + +Possible values: close, +commit, nontx-read + + +Description: A comma-separated list of events +when managed instances will be automatically detached. + +
+
+ + openjpa.BrokerFactory + + + + BrokerFactory + + + +Property name: openjpa.BrokerFactory + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getBrokerFactory + + + +Resource adaptor config-property: +BrokerFactory + + +Default: jdbc + + +Possible values: jdbc, +abstractstore, remote + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.kernel.BrokerFactory type to +use. + +
+
+ + openjpa.BrokerImpl + + + + BrokerImpl + + + + + Broker + + + BrokerImpl + + + +Property name: openjpa.BrokerImpl + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getBrokerImpl + + + +Resource adaptor config-property: +BrokerImpl + + +Default: default + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.kernel.Broker type to use at runtime. See + on for details. + +
+ +
+ openjpa.Callbacks + + Callbacks + + + Callbacks + Callbacks + + + Property name: openjpa.Callbacks + + + Configuration API: + + org.apache.openjpa.conf.OpenJPAConfiguration.getCallbackOptionsInstance + + + Resource adaptor config-property: Callbacks + + + Default: default + + + Description: A plugin string (see +) to fine tune some of the configurable +properties related to callbacks. The plug-in supports two boolean properties: + + + + PostPersistCallbackImmediate: whether the + post-persist callback is invoked as soon as a new instance + is managed. The default is false, implies that + the post-persist callback is invoked after the instance been committed + or flushed to the datastore. + + + + AllowsMultipleMethodsForSameCallback: whether + multiple methods of the same class can handle the same callback event. + Defaults to false. + + + +
+ +
+ + openjpa.ClassResolver + + + + ClassResolver + + + + + class loading + + + ClassResolver + + + +Property name: openjpa.ClassResolver + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getClassResolver + + + +Resource adaptor config-property: +ClassResolver + + +Default: default + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.util.ClassResolver implementation to use +for class name resolution. You may wish to plug in your own resolver if you have +special classloading needs. + +
+
+ + openjpa.Compatibility + + + + Compatibility + + + + + backwards compatibility + + + +Property name: openjpa.Compatibility + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getCompatibility + + + +Resource adaptor config-property: +Compatibility + + +Default: - + + +Description: Encapsulates options to mimic the +behavior of previous OpenJPA releases. + +
+
+ + openjpa.ConnectionDriverName + + + + ConnectionDriverName + + + + + connections + + + ConnectionDriverName + + + +Property name: +openjpa.ConnectionDriverName + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionDriverName + + + +Resource adaptor config-property: +ConnectionDriverName + + +Default: - + + +Description: The full class name of either the +JDBC java.sql.Driver, or a +javax.sql.DataSource implementation to use to connect to the +database. See for details. + +
+
+ + openjpa.Connection2DriverName + + + + Connection2DriverName + + + + + connections + + + Connection2DriverName + + + +Property name: +openjpa.Connection2DriverName + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2DriverName + + + +Resource adaptor config-property: +Connection2DriverName + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionDriverName property described in +, but applies to the +alternate connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionFactory + + + + ConnectionFactory + + + + + connections + + + ConnectionFactory + + + +Property name: +openjpa.ConnectionFactory + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory + + + +Resource adaptor config-property: +ConnectionFactory + + +Default: - + + +Description: A javax.sql.DataSource + to use to connect to the database. See + for details. + +
+
+ + openjpa.ConnectionFactory2 + + + + ConnectionFactory2 + + + + + connections + + + ConnectionFactory2 + + + +Property name: +openjpa.ConnectionFactory2 + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2 + + + +Resource adaptor config-property: +ConnectionFactory2 + + +Default: - + + +Description: An unmanaged +javax.sql.DataSource to use to connect to the database. See + for details. + +
+
+ + openjpa.ConnectionFactoryName + + + + ConnectionFactoryName + + + + + connections + + + ConnectionFactoryName + + + +Property name: +openjpa.ConnectionFactoryName + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryName + + + +Resource adaptor config-property: +ConnectionFactoryName + + +Default: - + + +Description: The JNDI location of a +javax.sql.DataSource to use to connect to the database. See + for details. + +
+
+ + openjpa.ConnectionFactory2Name + + + + ConnectionFactory2Name + + + + + connections + + + ConnectionFactory2Name + + + +Property name: +openjpa.ConnectionFactory2Name + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2Name + + + +Resource adaptor config-property: +ConnectionFactory2Name + + +Default: - + + +Description: The JNDI location of an unmanaged +javax.sql.DataSource to use to connect to the database. +See for details. + +
+
+ + openjpa.ConnectionFactoryMode + + + + ConnectionFactoryMode + + + + + connections + + + ConnectionFactoryMode + + + +Property name: +openjpa.ConnectionFactoryMode + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryMode + + + +Resource adaptor config-property: +ConnectionFactoryMode + + +Default: local + + +Possible values: local, +managed + + +Description: The connection factory mode to use +when integrating with the application server's managed transactions. See + for details. + +
+
+ + openjpa.ConnectionFactoryProperties + + + + ConnectionFactoryProperties + + + + + connections + + + ConnectionFactoryProperties + + + +Property name: +openjpa.ConnectionFactoryProperties + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactoryProperties + + + +Resource adaptor config-property: +ConnectionFactoryProperties + + +Default: - + + +Description: A plugin string (see +) listing properties for +configuration of the datasource in use. See the + for details. + +
+
+ + openjpa.ConnectionFactory2Properties + + + + ConnectionFactory2Properties + + + + + connections + + + ConnectionFactory2Properties + + + +Property name: +openjpa.ConnectionFactory2Properties + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionFactory2Properties + + + +Resource adaptor config-property: +ConnectionFactory2Properties + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionFactoryProperties property described in +, but applies to the +alternate connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionPassword + + + + ConnectionPassword + + + + + connections + + + ConnectionPassword + + + +Property name: +openjpa.ConnectionPassword + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionPassword + + + +Resource adaptor config-property: +ConnectionPassword + + +Default: - + + +Description: The password for the user +specified in the ConnectionUserName property. See + for details. + +
+
+ + openjpa.Connection2Password + + + + Connection2Password + + + + + connections + + + Connection2Password + + + +Property name: +openjpa.Connection2Password + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2Password + + + +Resource adaptor config-property: +Connection2Password + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionPassword property described in +, but applies to the +alternate connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionProperties + + + + ConnectionProperties + + + + + connections + + + ConnectionProperties + + + +Property name: +openjpa.ConnectionProperties + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionProperties + + + +Resource adaptor config-property: +ConnectionProperties + + +Default: - + + +Description: A plugin string (see +) listing properties to configure +the driver listed in the ConnectionDriverName property +described below. See for details. + +
+
+ + openjpa.Connection2Properties + + + + Connection2Properties + + + + + connections + + + Connection2Properties + + + +Property name: +openjpa.Connection2Properties + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2Properties + + + +Resource adaptor config-property: +Connection2Properties + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionProperties property described in +, but applies to the +alternate connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionURL + + + + ConnectionURL + + + + + connections + + + ConnectionURL + + + +Property name: openjpa.ConnectionURL + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionURL + + + +Resource adaptor config-property: +ConnectionURL + + +Default: - + + +Description: The JDBC URL for the database. See + for details. + +
+
+ + openjpa.Connection2URL + + + + Connection2URL + + + + + connections + + + Connection2URL + + + +Property name: openjpa.Connection2URL + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2URL + + + +Resource adaptor config-property: +Connection2URL + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionURL property described in +, but applies to the alternate +connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionUserName + + + + ConnectionUserName + + + + + connections + + + ConnectionUserName + + + +Property name: +openjpa.ConnectionUserName + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionUserName + + + +Resource adaptor config-property: +ConnectionUserName + + +Default: - + + +Description: The user name to use when +connecting to the database. See the +for details. + +
+
+ + openjpa.Connection2UserName + + + + Connection2UserName + + + + + connections + + + Connection2UserName + + + +Property name: +openjpa.Connection2UserName + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnection2UserName + + + +Resource adaptor config-property: +Connection2UserName + + +Default: - + + +Description: This property is equivalent to the +openjpa.ConnectionUserName property described in +, but applies to the +alternate connection factory used for unmanaged connections. See + for details. + +
+
+ + openjpa.ConnectionRetainMode + + + + ConnectionRetainMode + + + + + connections + + + ConnectionRetainMode + + + +Property name: +openjpa.ConnectionRetainMode + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getConnectionRetainMode + + + +Resource adaptor config-property: +ConnectionRetainMode + + +Default: on-demand + + +Description: Controls how OpenJPA uses +datastore connections. This property can also be specified for individual +sessions. See for details. + +
+
+ + openjpa.DataCache + + + + DataCache + + + + + caching + + + DataCache + + + +Property name: openjpa.DataCache + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getDataCache + + + +Resource adaptor config-property: +DataCache + + +Default: false + + +Description: A plugin list string (see +) describing the + +org.apache.openjpa.datacache.DataCaches to use for data +caching. See for details. + +
+
+ + openjpa.DataCacheManager + + + + DataCacheManager + + + + + caching + + + DataCacheManager + + + +Property name: +openjpa.DataCacheManager + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getDataCacheManager + + + +Resource adaptor config-property: +DataCacheManager + + +Default: default + + +Description: A plugin string (see +) describing the + +openjpa.datacache.DataCacheManager that manages +the system data caches. See for details +on data caching. + +
+
+ + openjpa.DataCacheTimeout + + + + DataCacheTimeout + + + + + caching + + + DataCacheTimeout + + + +Property name: +openjpa.DataCacheTimeout + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getDataCacheTimeout + + + +Resource adaptor config-property: +DataCacheTimeout + + +Default: -1 + + +Description: The number of milliseconds that +data in the data cache is valid. Set this to -1 to indicate that data should not +expire from the cache. This property can also be specified for individual +classes. See for details. + +
+
+ + openjpa.DetachState + + + + DetachState + + + + + detach + + + DetachState + + + DetachState + + + +Property name: openjpa.DetachState + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getDetachState + + + +Resource adaptor config-property: +DetachState + + +Default: loaded + + +Possible values: loaded, +fetch-groups, all + + +Description: Determines which fields are part +of the detached graph and related options. For more details, see +. + +
+
+ + openjpa.DynamicDataStructs + + + + DynamicDataStructs + + + + + caching + + + DynamicDataStructs + + + + + remote + + + DynamicDataStructs + + + +Property name: +openjpa.DynamicDataStructs + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getDynamicDataStructs + + + +Resource adaptor config-property: +DynamicDataStructs + + +Default: false + + +Description: Whether to dynamically generate +customized structs to hold persistent data. Both the OpenJPA data cache and the +remote framework rely on data structs to cache and transfer persistent state. +With dynamic structs, OpenJPA can customize data storage for each class, +eliminating the need to generate primitive wrapper objects. This saves memory +and speeds up certain runtime operations. The price is a longer warm-up time for +the application - generating and loading custom classes into the JVM takes time. +Therefore, only set this property to true if you have a +long-running application where the initial cost of class generation is offset by +memory and speed optimization over time. + +
+
+ + openjpa.FetchBatchSize + + + + FetchBatchSize + + + + + large result sets + + + FetchBatchSize + + + +Property name: openjpa.FetchBatchSize + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getFetchBatchSize + + + +Resource adaptor config-property: +FetchBatchSize + + +Default: -1 + + +Description: The number of rows to fetch at +once when scrolling through a result set. The fetch size can also be set at +runtime. See for details. + +
+
+ + openjpa.FetchGroups + + + + fetch groups + + + FetchGroups + + + +Property name: openjpa.FetchGroups + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getFetchGroups + + + +Resource adaptor config-property: +FetchGroups + + +Default: - + + +Description: A comma-separated list of fetch +group names that are to be loaded when retrieving objects from the datastore. +Fetch groups can also be set at runtime. See + for details. + +
+ +
+ + openjpa.FlushBeforeQueries + + + + FlushBeforeQueries + + + + + Query + + + FlushBeforeQueries + + + + + flush + + + FlushBeforeQueries + + + +Property name: +openjpa.FlushBeforeQueries + + +Property name: +openjpa.FlushBeforeQueries + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getFlushBeforeQueries + + + +Resource adaptor config-property: +FlushBeforeQueries + + +Default: true + + +Description: Whether or not to flush any +changes made in the current transaction to the datastore before executing a +query. See for details. + +
+
+ + openjpa.IgnoreChanges + + + + IgnoreChanges + + + +Property name: openjpa.IgnoreChanges + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getIgnoreChanges + + + +Resource adaptor config-property: +IgnoreChanges + + +Default: false + + +Description: Whether to consider modifications +to persistent objects made in the current transaction when evaluating queries. +Setting this to true allows OpenJPA to ignore changes and +execute the query directly against the datastore. A value of false + forces OpenJPA to consider whether the changes in the current +transaction affect the query, and if so to either evaluate the query in-memory +or flush before running it against the datastore. + +
+
+ openjpa.Id + + Id + + + Property name: + openjpa.Id + + + Resource adaptor config-property: + Id + + + Default: none + + + Description: An + environment-specific identifier for this configuration. This + might correspond to a JPA persistence-unit name, or to some other + more-unique value available in the current environment. + +
+ +InitializeEagerly +
+ + openjpa.InitializeEagerly + + + + InverseManager + + + + + Initialization + + + Configuration + + + +Property name: openjpa.InitializeEagerly + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.isInitializeEagerly + + + +Resource adaptor config-property: +InitializeEagerly + + +Default: false + + +Possible values: false, +true + + +Description: Controls whether initialization +is eager or lazy. Eager initialization imply all persistent classes, their +mapping information, database connectivity and all other resources specified in +the configuration of a persistence unit will be initialized when a persistent +unit is constructed. The default behavior is +lazy i.e. persistent classes, database and other resources are initialized only +when the application refers to a resource for the first time. + +
+ + + +
+ + openjpa.InverseManager + + + + InverseManager + + + + + bidirectional relation + + + InverseManager + + + +Property name: openjpa.InverseManager + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getInverseManager + + + +Resource adaptor config-property: +InverseManager + + +Default: false + + +Possible values: false, +true + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.kernel.InverseManager to use +for managing bidirectional relations upon a flush. See + for usage documentation. + +
+
+ + openjpa.LockManager + + + + LockManager + + + + + locking + + + LockManager + + + +Property name: openjpa.LockManager + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getLockManager + + + +Resource adaptor config-property: +LockManager + + +Default: mixed + + +Possible values: none, +sjvm, version, +pessimistic, mixed + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.kernel.LockManager to use for acquiring +locks on persistent instances during transactions. See + for more information. + +
+
+ + openjpa.LockTimeout + + + + LockTimeout + + + + + locking + + + LockTimeout + + + +Property name: openjpa.LockTimeout + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getLockTimeout + + + +Resource adaptor config-property: +LockTimeout + + +Default: -1 + + +Description: The number of milliseconds to wait +for an object lock before throwing an exception, or -1 for no limit. See + for details. + +
+
+ + openjpa.Log + + + + Log + + + + + logging + + + Log + + + +Property name: openjpa.Log + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getLog + + + +Resource adaptor config-property: Log + + + +Default: true + + +Possible values: openjpa, +commons, log4j, none + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.lib.log.LogFactory to use for logging. +For details on logging, see . + +
+
+ + openjpa.ManagedRuntime + + + + ManagedRuntime + + + + + transactions + + + managed + + + ManagedRuntime + + + +Property name: openjpa.ManagedRuntime + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getManagedRuntime + + + +Resource adaptor config-property: +ManagedRuntime + + +Default: auto + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.ee.ManagedRuntime implementation to use +for obtaining a reference to the TransactionManager in an +enterprise environment. + +
+
+ + openjpa.Mapping + + + + Mapping + + + +Property name: openjpa.Mapping + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getMapping + + + +Resource adaptor config-property: +Mapping + + +Default: - + + +Description: The symbolic name of the +object-to-datastore mapping to use. + +
+
+ + openjpa.MaxFetchDepth + + + + MaxFetchDepth + + + + + eager fetching + + + MaxFetchDepth + + + +Property name: openjpa.MaxFetchDepth + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getMaxFetchDepth + + + +Resource adaptor config-property: +MaxFetchDepth + + +Default: -1 + + +Description: The maximum depth of relations to +traverse when eager fetching. Use -1 for no limit. Defaults to no limit. See + for details on eager fetching. + +
+
+ + openjpa.MetaDataFactory + + + + MetaDataFactory + + + + + metadata + + + MetaDataFactory + + + +Property name: openjpa.MetaDataFactory + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getMetaDataFactory + + + +Resource adaptor config-property: +MetaDataFactory + + +Default: jpa + + +Description: A plugin string (see +) describing the + +openjpa.meta.MetaDataFactory to use to store and +retrieve metadata for your persistent classes. See + for details. + +
+
+ + openjpa.Multithreaded + + + + Multithreaded + + + + + threading + + + Multithreaded + + + +Property name: openjpa.Multithreaded + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getMultithreaded + + + +Resource adaptor config-property: +Multithreaded + + +Default: false + + +Description: Whether persistent instances and +OpenJPA components other than the EntityManagerFactory +will be accessed by multiple threads at once. + +
+
+ + openjpa.Optimistic + + + + Optimistic + + + + + transactions + + + optimistic + + + +Property name: openjpa.Optimistic + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getOptimistic + + + +Resource adaptor config-property: +Optimistic + + +Default: true + + +Description: Selects between optimistic and +pessimistic (datastore) transactional modes. + +
+
+ + openjpa.OrphanedKeyAction + + + + OrphanedKeyAction + + + + + foreign keys + + + OrphanedKeyAction + + + +Property name: +openjpa.OrphanedKeyAction + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getOrphanedKeyAction + + + +Resource adaptor config-property: +OrphanedKeyAction + + +Default: log + + +Possible values: log, +exception, none + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.event.OrphanedKeyAction to +invoke when OpenJPA discovers an orphaned datastore key. See + for details. + +
+
+ + openjpa.NontransactionalRead + + + + NontransactionalRead + + + +Property name: +openjpa.NontransactionalRead + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getNontransactionalRead + + + +Resource adaptor config-property: +NontransactionalRead + + +Default: true + + +Description: Whether the OpenJPA runtime will +allow you to read data outside of a transaction. + +
+
+ + openjpa.NontransactionalWrite + + + + NontransactionalWrite + + + +Property name: +openjpa.NontransactionalWrite + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getNontransactionalWrite + + + +Resource adaptor config-property: +NontransactionalWrite + + +Default: true + + +Description: Whether you can modify persistent +objects and perform persistence operations outside of a transaction. Changes +will take effect on the next transaction. + +
+
+ + openjpa.ProxyManager + + + + ProxyManager + + + + + proxies + + + ProxyManager + + + +Property name: openjpa.ProxyManager + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getProxyManager + + + +Resource adaptor config-property: +ProxyManager + + +Default: default + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.util.ProxyManager to use for proxying +mutable second class objects. See + for details. + +
+
+ + openjpa.QueryCache + + + + QueryCache + + + + + caching + + + QueryCache + + + +Property name: openjpa.QueryCache + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getQueryCache + + + +Resource adaptor config-property: +QueryCache + + +Default: true, when the data +cache (see ) is also enabled, +false otherwise. + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.datacache.QueryCache +implementation to use for caching of queries loaded from the data store. See + for details. + +
+
+ + openjpa.QueryCompilationCache + + + + QueryCompilationCache + + + + + caching + + + QueryCompilationCache + + + +Property name: +openjpa.QueryCompilationCache + + +Resource adaptor config-property: +QueryCompilationCache + + +Default: true. + + +Description: A plugin string (see +) describing the +java.util.Map to use for caching of data used during +query compilation. See for details. + +
+
+ + openjpa.ReadLockLevel + + + + ReadLockLevel + + + + + locking + + + ReadLockLevel + + + +Property name: openjpa.ReadLockLevel + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getReadLockLevel + + + +Resource adaptor config-property: +ReadLockLevel + + +Default: read + + +Possible values: none, +read, write, +optimistic, optimistic-force-increment, +pessimistic-read, pessimistic-write, +pessimistic-force-increment, numeric values for +lock-manager specific lock levels + + +Description: The default level at which to lock +objects retrieved during a non-optimistic transaction. Note that for the default +JDBC lock manager, read and write lock +levels are equivalent. Lock levels pessimistic-read, +pessimistic-write and +pessimistic-force-increment are in effect only when the +mixed lock manager is used. + +
+
+ + openjpa.RemoteCommitProvider + + + + RemoteCommitProvider + + + + + caching + + + RemoteCommitProvider + + + + + remote + + + RemoteCommitProvider + + + +Property name: +openjpa.RemoteCommitProvider + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getRemoteCommitProvider + + + +Resource adaptor config-property: +RemoteCommitProvider + + +Default: - + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.event.RemoteCommitProvider +implementation to use for distributed event notification. See + for more information. + +
+
+ + openjpa.RestoreState + + + + RestoreState + + + +Property name: openjpa.RestoreState + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getRestoreState + + + +Resource adaptor config-property: +RestoreState + + +Default: none + + +Possible values: none, +immutable, all + + +Description: Whether to restore managed fields +to their pre-transaction values when a rollback occurs. + +
+
+ + openjpa.RetainState + + + + RetainState + + + +Property name: openjpa.RetainState + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getRetainState + + + +Resource adaptor config-property: +RetainState + + +Default: true + + +Description: Whether persistent fields retain +their values on transaction commit. + +
+
+ + openjpa.RetryClassRegistration + + + + RetryClassRegistration + + + + + metadata + + + RetryClassRegistration + + + +Property name: +openjpa.RetryClassRegistration + + +Configuration API: + + +org.apache.openjpa.conf.OpenJPAConfiguration.getRetryClassRegistration + + + +Resource adaptor config-property: +RetryClassRegistration + + +Default: false + + +Description: Controls whether to log a warning +and defer registration instead of throwing an exception when a persistent class +cannot be fully processed. This property should only be +used in complex classloader situations where security is preventing OpenJPA from +reading registered classes. Setting this to true unnecessarily may obscure more +serious problems. + +
+
+ openjpa.RuntimeUnenhancedClasses + + Property name: + openjpa.RuntimeUnenhancedClasses + + + Configuration API: + org.apache.openjpa.conf.OpenJPAConfiguration.getRuntimeUnenhancedClasses + + + Resource adaptor config property: + RuntimeUnenhancedClasses + + + Default: + supported + + + + Possible values: + supported, + unsupported, + warn + + + Description: + The RuntimeUnenhancedClasses property controls how OpenJPA + handles classes that have not been enhanced by the PCEnhancer + tool or automatically by a javaagent. If RuntimeUnenhancedClasses is + set to supported OpenJPA will automatically + create subclasses for unenhanced entity classes. If set to + unsupported OpenJPA will not create subclasses + for unenhanced entity classes and will throw an exception when + they are detected. If set to warn OpenJPA + will not create subclasses for unenhanced entity classes + but will log a warning message. + + + See the reference guide section on unenhanced types for more + information + + +
+
+ + openjpa.SavepointManager + + +Property name: +openjpa.SavepointManager + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getSavepointManager + + +Resource adaptor config-property: +SavepointManager + + +Default: in-mem + + +Possible values: in-mem, +jdbc, oracle + + +Description: A plugin string (see +) describing a + +org.apache.openjpa.kernel.SavepointManager to +use for managing transaction savepoints. See + for details. + +
+
+ + openjpa.Sequence + + + + Sequence + + + +Property name: openjpa.Sequence + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getSequence + + + +Resource adaptor config-property: +Sequence + + +Default: table + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.kernel.Seq implementation to use for the +system sequence. See for more +information. + +
+
+ + openjpa.Specification + + + + Specification + + + +Property name: openjpa.Specification + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getSpecificationInstance + + + +Resource adaptor config-property: +Specification + + +Default: table + + +Description: A formatted string describing the Specification +to use for the default configuration options. The format of the Specifcation string is +name [major.[minor]] where name denotes the name of the +Specification such as JPA or JDO, major +denotes the major integral version number of the Specification and minor +denotes a minor version which can be an arbitrary string. +See for more information. + +
+ +
+ + openjpa.TransactionMode + + + + TransactionMode + + + + + transactions + + + TransactionMode + + + +Property name: openjpa.TransactionMode + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getTransactionMode + + + +Resource adaptor config-property: +TransactionMode + + +Default: local + + +Possible values: local, +managed + + +Description: The default transaction mode to +use. You can override this setting per-session. + +
+
+ + openjpa.WriteLockLevel + + + + WriteLockLevel + + + + + locking + + + WriteLockLevel + + + +Property name: openjpa.WriteLockLevel + + + +Configuration API: + +org.apache.openjpa.conf.OpenJPAConfiguration.getWriteLockLevel + + + +Resource adaptor config-property: +WriteLockLevel + + +Default: write + + +Possible values: none, +read, write, +optimistic, optimistic-force-increment, +pessimistic-read, pessimistic-write, +pessimistic-force-increment, numeric values for +lock-manager specific lock levels. + + +Description: The default level at which to lock +objects changed during a non-optimistic transaction. Note that for the default +JDBC lock manager, read and write lock +levels are equivalent. Lock levels pessimistic-read, +pessimistic-write and +pessimistic-force-increment are in effect only when the +mixed lock manager is used. + +
+
+
+ + OpenJPA JDBC Properties + + + + configuration + + + of JDBC properties + + + +The following properties apply exclusively to the OpenJPA JDBC back-end. + +
+ + openjpa.jdbc.ConnectionDecorators + + + + ConnectionDecorators + + + + + connections + + + ConnectionDecorators + + + +Property name: +openjpa.jdbc.ConnectionDecorators + + +Configuration API: + + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getConnectionDecorators + + + +Resource adaptor config-property: +ConnectionDecorators + + +Default: - + + +Description: A comma-separated list of plugin +strings (see ) describing + +org.apache.openjpa.lib.jdbc.ConnectionDecorator +instances to install on the connection factory. These decorators can wrap +connections passed from the underlying DataSource to add +functionality. OpenJPA will pass all connections through the list of decorators +before using them. Note that by default OpenJPA employs all +of the built-in decorators in the org.apache.openjpa.lib.jdbc + package already; you do not need to list them here. + +
+
+ + openjpa.jdbc.DBDictionary + + + + DBDictionary + + + + + JDBC + + + DBDictionary + + + +Property name: +openjpa.jdbc.DBDictionary + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getDBDictionary + + + +Resource adaptor config-property: +DBDictionary + + +Default: Based on the +openjpa.ConnectionURL + +openjpa.ConnectionDriverName + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.jdbc.sql.DBDictionary to use +for database interaction. OpenJPA typically auto-configures the dictionary based +on the JDBC URL, but you may have to set this property explicitly if you are +using an unrecognized driver, or to plug in your own dictionary for a database +OpenJPA does not support out-of-the-box. See + for details. + +
+
+ + openjpa.jdbc.DriverDataSource + + + + DriverDataSource + + + + + JDBC + + + DriverDataSource + + + +Property name: +openjpa.jdbc.DriverDataSource + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getDriverDataSource + + + +Resource adaptor config-property: +DriverDataSource + + +Default: pooling + + +Description: The alias or full class name of +the + +org.apache.openjpa.jdbc.schema.DriverDataSource +implementation to use to wrap JDBC Driver classes with javax.sql.DataSource +instances. + +
+
+ + openjpa.jdbc.EagerFetchMode + + + + EagerFetchMode + + + + + eager fetching + + + EagerFetchMode + + + +Property name: +openjpa.jdbc.EagerFetchMode + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getEagerFetchMode + + + +Resource adaptor config-property: +EagerFetchMode + + +Default: parallel + + +Possible values: parallel, +join, none + + +Description: Optimizes how OpenJPA loads +persistent relations. This setting can also be varied at runtime. See + for details. + +
+
+ + openjpa.jdbc.FetchDirection + + + + FetchDirection + + + + + large result sets + + + FetchDirection + + + +Property name: +openjpa.jdbc.FetchDirection + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getFetchDirection + + + +Resource adaptor config-property: +FetchDirection + + +Default: forward + + +Possible values: forward, +reverse, unknown + + +Description: The expected order in which query +result lists will be accessed. This property can also be varied at runtime. See + for details. + +
+
+ + openjpa.jdbc.JDBCListeners + + + + JDBCListeners + + + + + JDBC + + + JDBCListeners + + + +Property name: +openjpa.jdbc.JDBCListeners + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getJDBCListeners + + + +Resource adaptor config-property: +JDBCListeners + + +Default: - + + +Description: A comma-separated list of plugin +strings (see ) describing + +org.apache.openjpa.lib.jdbc.JDBCListener event +listeners to install. These listeners will be notified on various JDBC-related +events. + +
+
+ + openjpa.jdbc.LRSSize + + + + LRSSize + + + + + large result sets + + + LRSSize + + + +Property name: openjpa.jdbc.LRSSize + + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getLRSSize + + + +Resource adaptor config-property: +LRSSize + + +Default: query + + +Possible values: query, +last, unknown + + +Description: The strategy to use to calculate +the size of a result list. This property can also be varied at runtime. See + for details. + +
+
+ + openjpa.jdbc.MappingDefaults + + + + MappingDefaults + + + + + mapping metadata + + + MappingDefaults + + + +Property name: +openjpa.jdbc.MappingDefaults + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getMappingDefaults + + + +Resource adaptor config-property: +MappingDefaults + + +Default: jpa + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.jdbc.meta.MappingDefaults to +use to define default column names, table names, and constraints for your +persistent classes. See for +details. + +
+
+ + openjpa.jdbc.MappingFactory + + + + MappingFactory + + + + + mapping metadata + + + MappingFactory + + + +Property name: +openjpa.jdbc.MappingFactory + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getMappingFactory + + + +Resource adaptor config-property: +MappingFactory + + +Default: - + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.meta.MetaDataFactory to use to +store and retrieve object-relational mapping information for your persistent +classes. See for details. + + +
+
+ + openjpa.jdbc.QuerySQLCache + + + + Prepared SQL Cache + + + + + caching + + + QuerySQLCache + + + +Property name: +openjpa.jdbc.QuerySQLCache + + +Resource adaptor config-property: +QuerySQLCache + + +Default: true. + + +Description: A plugin string (see +) describing the options to cache and +reuse SQL statements generated for JPQL queries. +See for details. + +
+
+ + openjpa.jdbc.ResultSetType + + + + ResultSetType + + + + + large result sets + + + ResultSetType + + + +Property name: +openjpa.jdbc.ResultSetType + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getResultSetType + + + +Resource adaptor config-property: +ResultSetType + + +Default: forward-only + + +Possible values: forward-only +, scroll-sensitive, scroll-insensitive + + +Description: The JDBC result set type to use +when fetching result lists. This property can also be varied at runtime. See + for details. + +
+
+ + openjpa.jdbc.Schema + + + + schema + + + Schema + + + +Property name: openjpa.jdbc.Schema + + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchema + + + +Resource adaptor config-property: +Schema + + +Default: - + + +Description: The default schema name to prepend +to unqualified table names. Also, the schema in which OpenJPA will create new +tables. See for details. + +
+
+ + openjpa.jdbc.SchemaFactory + + + + SchemaFactory + + + + + schema + + + SchemaFactory + + + +Property name: +openjpa.jdbc.SchemaFactory + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchemaFactory + + + +Resource adaptor config-property: +SchemaFactory + + +Default: dynamic + + +Possible values: dynamic, +native, file, table, +others + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.jdbc.schema.SchemaFactory to +use to store and retrieve information about the database schema. See + for details. + +
+
+ + openjpa.jdbc.Schemas + + + + schema + + + Schemas + + + +Property name: openjpa.jdbc.Schemas + + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSchemas + + + +Resource adaptor config-property: +Schemas + + +Default: - + + +Description: A comma-separated list of the +schemas and/or tables used for your persistent data. See + for details. + +
+
+ + openjpa.jdbc.SQLFactory + + + + SQLFactory + + + + + SQL + + + SQLFactory + + + +Property name: openjpa.jdbc.SQLFactory + + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSQLFactory + + + +Resource adaptor config-property: +SQLFactory + + +Default: default + + +Description: A plugin string (see +) describing the + +org.apache.openjpa.jdbc.sql.SQLFactory to use to abstract +common SQL constructs. + +
+
+ + openjpa.jdbc.SubclassFetchMode + + + + SubclassFetchMode + + + + + eager fetching + + + SubclassFetchMode + + + + + inheritance + + + SubclassFetchMode + + + +Property name: +openjpa.jdbc.SubclassFetchMode + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSubclassFetchMode + + + +Resource adaptor config-property: +SubclassFetchMode + + +Default: parallel + + +Possible values: parallel, +join, none + + +Description: How to select subclass data when +it is in other tables. This setting can also be varied at runtime. See +. + +
+
+ + openjpa.jdbc.SynchronizeMappings + + + + SynchronizeMappings + + + + + mapping metadata + + + SynchronizeMappings + + + +Property name: +openjpa.jdbc.SynchronizeMappings + + +Configuration API: + + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getSynchronizeMappings + + + +Resource adaptor config-property: +SynchronizeMappings + + +Default: - + + +Description: Controls whether OpenJPA will +attempt to run the mapping tool on all persistent classes to synchronize their +mappings and schema at runtime. Useful for rapid test/debug cycles. See + for more information. + +
+
+ + openjpa.jdbc.TransactionIsolation + + + + TransactionIsolation + + + + + transactions + + + TransactionIsolation + + + + + JDBC + + + TransactionIsolation + + + +Property name: +openjpa.jdbc.TransactionIsolation + + +Configuration API: + + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getTransactionIsolation + + + +Resource adaptor config-property: +TransactionIsolation + + +Default: default + + +Possible values: default, +none, read-committed, +read-uncommitted, repeatable-read, +serializable + + +Description: The JDBC transaction isolation +level to use. See for +details. + +
+
+ + openjpa.jdbc.UpdateManager + + + + UpdateManager + + + + + JDBC + + + UpdateManager + + + +Property name: +openjpa.jdbc.UpdateManager + + +Configuration API: + +org.apache.openjpa.jdbc.conf.JDBCConfiguration.getUpdateManager + + + +Resource adaptor config-property: +UpdateManager + + +Default: batching-constraint + + + Possible values: default, +operation-order, constraint, +batching-constraint, batching-operation-order + + +Description: The full class name of the + +org.apache.openjpa.jdbc.kernel.UpdateManager to +use to flush persistent object changes to the datastore. The provided default +implementation is + +org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager +. + + +
+ +
+ Compatibility with Specification + +The default behavior of certain OpenJPA API methods can evolve to align with the behaviors +defined in JPA specification. To maintain backward compatibility, OpenJPA allows configuration +options such that while the default behavior changes to align with current JPA Specification, the +previous behaviors can always be emulated. + + +For example, JPA 2.0 specification +introduces a new API void EntityManager.detach(Object entity) that detaches +the given entity from the current persistence context. OpenJPA has provided similar +feature via <T> T OpenJPAEntityManager.detach(T entity) prior to JPA 2.0. +OpenJPA detach(), however, has different default behavior than what JPA 2.0 +specification mandates. Firstly, OpenJPA creates a copy of the given entity as a detached instance +and returns it, whereas JPA 2.0 behavior requires the same given entity instance be detached. +Secondly, the given instance is removed from the persistence context for JPA 2.0, whereas +OpenJPA detach() method, prior to JPA 2.0, does not remove the instance +from the persistence context as a copy is returned. Thirdly, OpenJPA will flush before +detaching a dirty instance so that the detached instance can later be merged, whereas +JPA 2.0 detach() semantics does not require a dirty instance be flushed +before detach. + + +A user application running with OpenJPA that is compliant to a specific version of JPA of specification, +the older behavior can be emulated by configuring OpenJPA Compatibility options. +For example, openjpa.Compatibility=FlushBeforeDetach=false,CopyOnDetach=true +will emulate the older behavior of detach even when running with OpenJPA that are +compliant to JPA 2.0 Specification. The configuration can also be set to a different version of the specification. +For example, openjpa.Specification="JPA 1.0" configuration setting will emulate +default OpenJPA behavior as it were for JPA Specification version 1.0. Setting via +openjpa.Specification is a shorthand for more fine-grained control available via +openjpa.Compatibility. + + +
+
+