org.babyfish.jimmer.sql.runtime.ExceptionTranslator Maven / Gradle / Ivy
Show all versions of jimmer-sql Show documentation
package org.babyfish.jimmer.sql.runtime;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Exception translator for database exception,
* no matter it is low-level JDBC exception,
* such as {@link java.sql.SQLException};
* or a relatively advanced Jimmer exception,
* such as @{@link SaveException.NotUnique}
*
* Example:
{@code
* new ExceptionTranslator() {
* @Override
* public @Nullable Exception translate(
* @NotNull SaveException.NotUnique exception,
* @NotNull Args args
* ) {
* if (exception.isMatched(BookProps.NAME, BookProps.EDITION)) {
* return new IllegalArgumentException(
* "The book whose name is \"" +
* exception.getValue(BookProps.NAME) +
* "\" and edition is \"" +
* exception.getValue(BookProps.EDITION) +
* "\" already exists"
* );
* }
* return null;
* }
* }
* }
*
* After being translated, exceptions can
* continue to be translated until there is no
* matching translator. To avoid potential infinite
* recursion problems, the same translator will
* not be used twice.
*
* If the final translated exception is
* {@link RuntimeException}, it will be thrown directly;
* otherwise, it will be wrapped and thrown as
* {@link ExecutionException}
*
* There are 3 ways to setup exception translators.
*
*
* - Add it to save command, like this
{@code
* sqlClient.getEntities()
* .saveCommand(...entity...)
* .addExceptionTranslator(
* new ExceptionTranslator() {
* ...
* }
* )
* }
This configuration has a higher priority. If the
* same exception type is configured twice by this method and
* the global configuration, the configuration of this method
* takes precedence.
* - Global configuration without spring-starter, like this
{@code
* JSqlClient sqlClient = JSqlClient
* .newBuilder()
* .addExceptionTranslator(
* new ExceptionTranslator() {
* ...
* }
* )
* }
* - Global configuration by jimmer-spring-starter,
* by {@code @Component} of spring framework, such as
{@code
* @Component // Let spring know your translator
* public NotUniqueExceptionTranslator
* implements ExceptionTranslator {
* ...
* }
* }
*
* @param The translated exception type.
* Note, this generic type must be specified by any class
* implements this interface, otherwise, exception will be raised
*/
public interface ExceptionTranslator {
/**
* Translate the exception.
*
* If the exception is not known how to be translated,
* return null or the original argument.
*/
@Nullable
default Exception translate(@NotNull E exception, @NotNull Args args) {
return exception;
}
interface Args {
JSqlClientImplementor sqlClient();
String sql();
ExecutionPurpose purpose();
ExecutorContext ctx();
}
static ExceptionTranslator of(Collection> translators) {
return RuntimeExceptionTranslator.of(translators);
}
}