mirror of https://github.com/apache/openjpa.git
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:
parent
616f8fdbee
commit
718370e1ef
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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()",
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue