[#901] Introduce InvalidResultException as a subtype of DataAccessException for integrity checks in methods like ResultQuery#fetchOne(), ResultQuery#fetchMap(), etc.

This commit is contained in:
Lukas Eder 2011-11-05 11:46:38 +00:00
parent 67acab88c0
commit 54e45189cc
6 changed files with 122 additions and 24 deletions

View File

@ -198,6 +198,7 @@ import org.jooq.UpdatableTable;
import org.jooq.UpdateQuery;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.DetachedException;
import org.jooq.exception.InvalidResultException;
import org.jooq.impl.CustomCondition;
import org.jooq.impl.CustomField;
import org.jooq.impl.Factory;
@ -952,7 +953,7 @@ public abstract class jOOQAbstractTest<
try {
create().selectFrom(TBook()).orderBy(TBook_ID()).fetchMap(TBook_AUTHOR_ID());
fail();
} catch (DataAccessException expected) {}
} catch (InvalidResultException expected) {}
// Key -> Record Map
// -----------------
@ -996,13 +997,13 @@ public abstract class jOOQAbstractTest<
create().select(val("a"), val("a")).fetchMaps();
fail();
}
catch (Exception expected) {}
catch (InvalidResultException expected) {}
try {
create().select(val("a"), val("a")).fetchOneMap();
fail();
}
catch (Exception expected) {}
catch (InvalidResultException expected) {}
}
@Test
@ -2692,7 +2693,7 @@ public abstract class jOOQAbstractTest<
q.fetchOne();
fail();
}
catch (Exception expected) {}
catch (InvalidResultException expected) {}
Record record = q.fetchAny();
assertEquals("Coelho", record.getValue(TAuthor_LAST_NAME()));
@ -3682,7 +3683,7 @@ public abstract class jOOQAbstractTest<
create().fetchOne(TAuthor());
fail();
}
catch (Exception expected) {}
catch (InvalidResultException expected) {}
A selectOne = create().fetchOne(TAuthor(), TAuthor_FIRST_NAME().equal("Paulo"));
assertEquals("Paulo", selectOne.getValue(TAuthor_FIRST_NAME()));
@ -3780,7 +3781,7 @@ public abstract class jOOQAbstractTest<
try {
book.refresh();
}
catch (DataAccessException expected) {}
catch (InvalidResultException expected) {}
// Fetch the original record
B book1 = create().fetchOne(TBook(), TBook_TITLE().equal("1984"));
@ -3914,7 +3915,7 @@ public abstract class jOOQAbstractTest<
try {
store.refresh();
}
catch (DataAccessException expected) {}
catch (InvalidResultException expected) {}
store.setValue(TBookStore_NAME(), "Rösslitor");
assertEquals(1, store.store());
@ -4016,7 +4017,7 @@ public abstract class jOOQAbstractTest<
record.refreshUsing(T785_VALUE());
fail();
}
catch (DataAccessException expected) {}
catch (InvalidResultException expected) {}
// Don't allow refreshing on inexistent results
@ -4026,7 +4027,7 @@ public abstract class jOOQAbstractTest<
record.refreshUsing(T785_ID());
fail();
}
catch (DataAccessException expected) {}
catch (InvalidResultException expected) {}
// Delete records again
record = create().newRecord(T785());

View File

@ -52,10 +52,22 @@ public class DetachedException extends DataAccessException {
*/
private static final long serialVersionUID = -6460945824599280420L;
/**
* Constructor for DataAccessException.
*
* @param message the detail message
*/
public DetachedException(String message) {
super(message);
}
/**
* Constructor for DataAccessException.
*
* @param message the detail message
* @param cause the root cause (usually from using a underlying data access
* API such as JDBC)
*/
public DetachedException(String message, Throwable cause) {
super(message, cause);
}

View File

@ -0,0 +1,89 @@
/**
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq.exception;
import org.jooq.Query;
import org.jooq.ResultQuery;
import org.jooq.TableRecord;
import org.jooq.UpdatableRecord;
/**
* An unexpected result was encountered after executing a {@link Query}. This
* exception indicates wrong usage of jOOQ's various fetch methods, or an
* integrity problem in your data.
* <p>
* This is typically the case in the following situations:
* <ul>
* <li>When you call methods such as {@link ResultQuery#fetchOne()} and the
* database returns more than one record.</li>
* <li>When you call methods such as
* {@link ResultQuery#fetchMap(org.jooq.Field)} and the database returns several
* records per key.</li>
* <li>When you refresh a {@link TableRecord} using
* {@link TableRecord#refreshUsing(org.jooq.TableField...)}, or
* {@link UpdatableRecord#refresh()}, and the record does not exist anymore in
* the database.</li>
* </ul>
*
* @author Lukas Eder
*/
public class InvalidResultException extends DataAccessException {
/**
* Generated UID
*/
private static final long serialVersionUID = -6460945824599280420L;
/**
* Constructor for DataAccessException.
*
* @param message the detail message
*/
public InvalidResultException(String message) {
super(message);
}
/**
* Constructor for DataAccessException.
*
* @param message the detail message
* @param cause the root cause (usually from using a underlying data access
* API such as JDBC)
*/
public InvalidResultException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -62,7 +62,7 @@ import org.jooq.RecordHandler;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.SQLDialect;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.InvalidResultException;
/**
* A query that returns a {@link Result}
@ -245,7 +245,7 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
return r.get(0);
}
else if (r.size() > 1) {
throw new DataAccessException("Query returned more than one result");
throw new InvalidResultException("Query returned more than one result");
}
return null;
@ -269,7 +269,7 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
for (R record : fetch()) {
if (map.put(record.getValue(key), record) != null) {
throw new DataAccessException("Key " + key + " is not unique in Result for " + this);
throw new InvalidResultException("Key " + key + " is not unique in Result for " + this);
}
}
@ -308,7 +308,7 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
for (Field<?> field : record.getFields()) {
if (map.put(field.getName(), record.getValue(field)) != null) {
throw new DataAccessException("Field " + field.getName() + " is not unique in Record for " + this);
throw new InvalidResultException("Field " + field.getName() + " is not unique in Record for " + this);
}
}

View File

@ -100,7 +100,7 @@ import org.jooq.UpdateQuery;
import org.jooq.UpdateSetStep;
import org.jooq.WindowIgnoreNullsStep;
import org.jooq.WindowOverStep;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.InvalidResultException;
/**
* A factory providing implementations to the org.jooq interfaces
@ -2924,20 +2924,16 @@ public class Factory implements FactoryOperations {
return i;
}
else {
throw new DataAccessException("Too many rows " + action + " : " + i);
throw new InvalidResultException("Too many rows " + action + " : " + i);
}
}
private static <R extends Record> R filterOne(List<R> list) {
if (list.size() == 0) {
return null;
}
else if (list.size() == 1) {
if (filterOne(list.size(), "selected") == 1) {
return list.get(0);
}
else {
throw new DataAccessException("Too many rows returned : " + list.size());
}
return null;
}
@Override

View File

@ -48,7 +48,7 @@ import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableRecord;
import org.jooq.UpdateQuery;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.InvalidResultException;
/**
* A record implementation for a record originating from a single table
@ -198,7 +198,7 @@ public class TableRecordImpl<R extends TableRecord<R>> extends TypeRecord<Table<
}
}
else {
throw new DataAccessException("Exactly one row expected for refresh. Record does not exist in database.");
throw new InvalidResultException("Exactly one row expected for refresh. Record does not exist in database.");
}
}