OPENJPA-957 - Create Fetch*HintHandler(s) for property processing in EntityManager/Query interface methods.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@762161 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Albert Lee 2009-04-05 21:29:42 +00:00
parent 616f8fdbee
commit 718370e1ef
32 changed files with 8455 additions and 5139 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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 <properties file or resource>]\n\
\t[-<property name> <property value>]*
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 <properties file or resource>]\n\
\t[-<property name> <property value>]*\n\
\t-action/-a <add | drop | get | set> [value]
clstable-seq-usage: Usage: \
java org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq\n\
\t[-properties/-p <properties file or resource>]\n\
\t[-<property name> <property value>]*\n\
\t-action/-a <add | drop | get | set>\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 <properties file or resource>]\n\
\t[-<property name> <property value>]*
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 <properties file or resource>]\n\
\t[-<property name> <property value>]*
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 <properties file or resource>]\n\
\t[-<property name> <property value>]*\n\
\t-action/-a <add | drop | get | set> [value]
clstable-seq-usage: Usage: \
java org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq\n\
\t[-properties/-p <properties file or resource>]\n\
\t[-<property name> <property value>]*\n\
\t-action/-a <add | drop | get | set>\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 <properties file or resource>]\n\
\t[-<property name> <property value>]*
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}.

View File

@ -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;
}
}

View File

@ -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<String, Object> getHints() {
try {
return _fetch.getHints();

View File

@ -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.
*

View File

@ -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<String, String> hintsMap =
new HashMap<String, String>();
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;
}
}

View File

@ -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);
}

View File

@ -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}.

View File

@ -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) {

View File

@ -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());
}
}

View File

@ -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<String,Object> props2 = new HashMap<String,Object>();
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();
}
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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()",

View File

@ -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

View File

@ -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();

View File

@ -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> T find(Class<T> cls, Object oid,
Map<String, Object> properties){
return find(cls, oid, null, properties);
}
@SuppressWarnings("unchecked")
public <T> T find(Class<T> cls, Object oid, LockModeType mode,
Map<String, Object> 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<String, Object> properties) {
refresh(entity, null, properties);
}
public void refresh(Object entity, LockModeType mode,
Map<String, Object> 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<String, Object> properties) {
boolean fcPushed = false;
if (properties != null && properties.size() > 0) {
Configuration conf = _broker.getConfiguration();
Set<String> inKeys = properties.keySet();
for (String inKey : inKeys) {
for (FetchConfigProperty validProp : validProps) {
String validPropStr = validProp.toString();
Set<String> 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<String, Object> 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<String, Object> 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> T find(Class<T> arg0, Object arg1, Map<String, Object> arg2) {
throw new UnsupportedOperationException(
"JPA 2.0 - Method not yet implemented");
}
}

View File

@ -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<String, Object> 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

View File

@ -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<String> ValidProductPrefixes =
new HashSet<String>();
// JPA Specification 2.0 keys are mapped to equivalent FetchPlan keys
protected static final Map<String, String> JavaxHintsMap =
new HashMap<String, String>();
// hints precedent definitions
protected static final Map<String, String[]> PrecedenceMap =
new HashMap<String, String[]>();
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;
}
}

View File

@ -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<String, Object> hints) {
if (hints != null && hints.size() > 0) {
for (String name : hints.keySet())
setHint(name, hints.get(name), false);
}
}
public Map<String, Object> getHints() {

View File

@ -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<String, Object> _hints;
private Set<String> _supportedKeys;
private Set<String> _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<String,String> _jpaKeys = new TreeMap<String, String>();
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<String> addPrefix(String prefix, Set<String> original) {
Set<String> result = new TreeSet<String>();
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<String> {
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<String> addPrefix(String prefix, Set<String> original) {
Set<String> result = new TreeSet<String>();
String join = prefix.endsWith(DOT) ? BLANK : DOT;
for (String o : original)
result.add(prefix + join + o);
return result;
}
}

View File

@ -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)

View File

@ -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}.

View File

@ -814,6 +814,40 @@ hints={ @QueryHint (name="openjpa.hint.OptimizeResultCount", value="2"),
</programlisting>
</example>
</section>
<section id="multi-hints-handling">
<title>
Handling of Multiple Similar Query Hints
</title>
<para>
When similar hints in different prefix scopes are specified in a query,
the following prefix precedence order is used to select the effective hint:
<itemizedlist>
<listitem>
javax.persistence.*
</listitem>
<listitem>
openjpa.FetchPlan.*
</listitem>
<listitem>
openjpa.jdbc.*
</listitem>
<listitem>
openjpa.*
</listitem>
</itemizedlist>
<example id="multi-hints-example">
<programlisting>
...
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
...
</programlisting>
</example>
</para>
</section>
</section>
<section id="jpa_overview_query_ordering">
<title>

File diff suppressed because it is too large Load Diff