diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java index 176d44a74..1156fceb4 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java @@ -51,6 +51,8 @@ import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InvalidStateException; +import org.apache.openjpa.util.NonUniqueResultException; +import org.apache.openjpa.util.NoResultException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; @@ -1279,10 +1281,10 @@ public class QueryImpl if (next) { single = rop.getResultObject(); if (range.end != range.start + 1 && rop.next()) - throw new InvalidStateException(_loc.get("not-unique", + throw new NonUniqueResultException(_loc.get("not-unique", _class, _query)); } else if (_unique == Boolean.TRUE) - throw new InvalidStateException(_loc.get("no-result", + throw new NoResultException(_loc.get("no-result", _class, _query)); // if unique set to false, use collection diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/NoResultException.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/NoResultException.java new file mode 100644 index 000000000..3c188d257 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/NoResultException.java @@ -0,0 +1,43 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import org.apache.openjpa.lib.util.Localizer.Message; + +/** + * Exception type thrown when a query was configured to return + * a single result, and no result was found. + * + * @since 0.9.7 + * @author Marc Prud'hommeaux + */ +public class NoResultException + extends InvalidStateException { + + public NoResultException(Message msg) { + super(msg); + } + + public NoResultException(Message msg, Object failed) { + super(msg); + setFailedObject(failed); + } + + public int getSubtype() { + return NO_RESULT; + } +} + diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/NonUniqueResultException.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/NonUniqueResultException.java new file mode 100644 index 000000000..242c9e6e7 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/NonUniqueResultException.java @@ -0,0 +1,43 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import org.apache.openjpa.lib.util.Localizer.Message; + +/** + * Exception type thrown when a query was configured to return + * a single result, and multiple results were found. + * + * @since 0.9.7 + * @author Marc Prud'hommeaux + */ +public class NonUniqueResultException + extends InvalidStateException { + + public NonUniqueResultException(Message msg) { + super(msg); + } + + public NonUniqueResultException(Message msg, Object failed) { + super(msg); + setFailedObject(failed); + } + + public int getSubtype() { + return NON_UNIQUE_RESULT; + } +} + diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/UserException.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/UserException.java index e7480499c..f44573d84 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/UserException.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/UserException.java @@ -30,6 +30,8 @@ public class UserException public static final int INVALID_STATE = 2; public static final int NO_TRANSACTION = 3; public static final int CALLBACK = 4; + public static final int NO_RESULT = 5; + public static final int NON_UNIQUE_RESULT = 6; public UserException() { } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java index 210ea4460..1f8339abc 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java @@ -173,6 +173,16 @@ public class PersistenceExceptions (ke.getMessage(), getNestedThrowables(ke), getFailedObject(ke), ke.isFatal()); break; + case UserException.NO_RESULT: + e = new org.apache.openjpa.persistence.NoResultException + (ke.getMessage(), getNestedThrowables(ke), + getFailedObject(ke), ke.isFatal()); + break; + case UserException.NON_UNIQUE_RESULT: + e = new org.apache.openjpa.persistence.NonUniqueResultException + (ke.getMessage(), getNestedThrowables(ke), + getFailedObject(ke), ke.isFatal()); + break; case UserException.INVALID_STATE: e = new org.apache.openjpa.persistence.InvalidStateException (ke.getMessage(), getNestedThrowables(ke), diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java index 18ce2987a..5def74057 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java @@ -281,26 +281,14 @@ public class QueryImpl */ public Object getSingleResult() { _em.assertNotCloseInvoked(); - Object ob = execute(); - if (!(ob instanceof List)) - return ob; - - List res = (List) ob; + // temporarily set query to unique so that a single result is validated + // and returned; unset again in case the user executes query again + // via getResultList + _query.setUnique(true); try { - // don't use size() b/c can be inefficient under some LRS settings - Iterator itr = res.iterator(); - if (!itr.hasNext()) - throw new NoResultException(_loc.get("no-results", - _query.getQueryString()).getMessage(), null, null, false); - - Object ret = itr.next(); - if (itr.hasNext()) - throw new NonUniqueResultException(_loc.get("mult-results", - _query.getQueryString()).getMessage(), null, null, false); - - return ret; + return execute(); } finally { - OpenJPAPersistence.close(res); + _query.setUnique(false); } }