[#901] Introduce InvalidResultException as a subtype of DataAccessException for integrity checks in methods like ResultQuery#fetchOne(), ResultQuery#fetchMap(), etc.
This commit is contained in:
parent
67acab88c0
commit
54e45189cc
@ -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());
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user