Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.landawn.abacus.jdbc.DaoImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2019, Haiyang Li.
*
* 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 com.landawn.abacus.jdbc;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.regex.Pattern;
import com.landawn.abacus.annotation.Internal;
import com.landawn.abacus.cache.Cache;
import com.landawn.abacus.cache.CacheFactory;
import com.landawn.abacus.condition.Condition;
import com.landawn.abacus.condition.ConditionFactory;
import com.landawn.abacus.condition.ConditionFactory.CF;
import com.landawn.abacus.condition.Criteria;
import com.landawn.abacus.condition.Expression;
import com.landawn.abacus.condition.Limit;
import com.landawn.abacus.condition.SubQuery;
import com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.exception.UncheckedSQLException;
import com.landawn.abacus.jdbc.Jdbc.BiParametersSetter;
import com.landawn.abacus.jdbc.Jdbc.BiRowMapper;
import com.landawn.abacus.jdbc.Jdbc.Columns.ColumnOne;
import com.landawn.abacus.jdbc.Jdbc.HandlerFactory;
import com.landawn.abacus.jdbc.annotation.Bind;
import com.landawn.abacus.jdbc.annotation.BindList;
import com.landawn.abacus.jdbc.annotation.CacheResult;
import com.landawn.abacus.jdbc.annotation.Call;
import com.landawn.abacus.jdbc.annotation.Config;
import com.landawn.abacus.jdbc.annotation.Define;
import com.landawn.abacus.jdbc.annotation.DefineList;
import com.landawn.abacus.jdbc.annotation.Delete;
import com.landawn.abacus.jdbc.annotation.FetchColumnByEntityClass;
import com.landawn.abacus.jdbc.annotation.Handler;
import com.landawn.abacus.jdbc.annotation.HandlerList;
import com.landawn.abacus.jdbc.annotation.Insert;
import com.landawn.abacus.jdbc.annotation.MappedByKey;
import com.landawn.abacus.jdbc.annotation.MergedById;
import com.landawn.abacus.jdbc.annotation.NonDBOperation;
import com.landawn.abacus.jdbc.annotation.OutParameter;
import com.landawn.abacus.jdbc.annotation.OutParameterList;
import com.landawn.abacus.jdbc.annotation.PerfLog;
import com.landawn.abacus.jdbc.annotation.PrefixFieldMapping;
import com.landawn.abacus.jdbc.annotation.RefreshCache;
import com.landawn.abacus.jdbc.annotation.Select;
import com.landawn.abacus.jdbc.annotation.SqlField;
import com.landawn.abacus.jdbc.annotation.SqlLogEnabled;
import com.landawn.abacus.jdbc.annotation.SqlMapper;
import com.landawn.abacus.jdbc.annotation.Sqls;
import com.landawn.abacus.jdbc.annotation.Transactional;
import com.landawn.abacus.jdbc.annotation.Update;
import com.landawn.abacus.jdbc.dao.CrudDao;
import com.landawn.abacus.jdbc.dao.CrudDaoL;
import com.landawn.abacus.jdbc.dao.CrudJoinEntityHelper;
import com.landawn.abacus.jdbc.dao.Dao;
import com.landawn.abacus.jdbc.dao.JoinEntityHelper;
import com.landawn.abacus.jdbc.dao.NoUpdateDao;
import com.landawn.abacus.jdbc.dao.UncheckedCrudDao;
import com.landawn.abacus.jdbc.dao.UncheckedCrudDaoL;
import com.landawn.abacus.jdbc.dao.UncheckedDao;
import com.landawn.abacus.jdbc.dao.UncheckedJoinEntityHelper;
import com.landawn.abacus.jdbc.dao.UncheckedNoUpdateDao;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.parser.JSONSerializationConfig;
import com.landawn.abacus.parser.JSONSerializationConfig.JSC;
import com.landawn.abacus.parser.KryoParser;
import com.landawn.abacus.parser.ParserFactory;
import com.landawn.abacus.parser.ParserUtil;
import com.landawn.abacus.parser.ParserUtil.BeanInfo;
import com.landawn.abacus.parser.ParserUtil.PropInfo;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.util.Array;
import com.landawn.abacus.util.AsyncExecutor;
import com.landawn.abacus.util.ClassUtil;
import com.landawn.abacus.util.DataSet;
import com.landawn.abacus.util.DateUtil.Dates;
import com.landawn.abacus.util.EntityId;
import com.landawn.abacus.util.Fn;
import com.landawn.abacus.util.Fn.IntFunctions;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.Holder;
import com.landawn.abacus.util.ImmutableList;
import com.landawn.abacus.util.ImmutableMap;
import com.landawn.abacus.util.ImmutableSet;
import com.landawn.abacus.util.Joiner;
import com.landawn.abacus.util.MutableBoolean;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.NamingPolicy;
import com.landawn.abacus.util.Numbers;
import com.landawn.abacus.util.Pair;
import com.landawn.abacus.util.ParsedSql;
import com.landawn.abacus.util.QueryUtil;
import com.landawn.abacus.util.SQLBuilder;
import com.landawn.abacus.util.SQLBuilder.NAC;
import com.landawn.abacus.util.SQLBuilder.NLC;
import com.landawn.abacus.util.SQLBuilder.NSC;
import com.landawn.abacus.util.SQLBuilder.PAC;
import com.landawn.abacus.util.SQLBuilder.PLC;
import com.landawn.abacus.util.SQLBuilder.PSC;
import com.landawn.abacus.util.SQLBuilder.SP;
import com.landawn.abacus.util.SQLMapper;
import com.landawn.abacus.util.Seq;
import com.landawn.abacus.util.Splitter;
import com.landawn.abacus.util.Splitter.MapSplitter;
import com.landawn.abacus.util.Strings;
import com.landawn.abacus.util.Throwables;
import com.landawn.abacus.util.Tuple;
import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.Tuple.Tuple3;
import com.landawn.abacus.util.WD;
import com.landawn.abacus.util.u;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.LongFunction;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.stream.BaseStream;
import com.landawn.abacus.util.stream.EntryStream;
import com.landawn.abacus.util.stream.IntStream.IntStreamEx;
import com.landawn.abacus.util.stream.Stream;
import com.landawn.abacus.util.stream.Stream.StreamEx;
@Internal
@SuppressWarnings({ "deprecation", "java:S1192" })
final class DaoImpl {
private DaoImpl() {
// singleton for utility class.
}
private static final int DEFAULT_CACHE_CAPACITY = 1000;
private static final int DEFAULT_EVICT_DELAY = 3000;
private static final String _1 = "1";
private static final String PN_NOW = "now";
static final ThreadLocal isInDaoMethod_TL = ThreadLocal.withInitial(() -> false);
private static final KryoParser kryoParser = ParserFactory.isKryoAvailable() ? ParserFactory.createKryoParser() : null;
private static final JSONSerializationConfig jsc_no_bracket = JSC.create().setStringQuotation(JdbcUtil.CHAR_ZERO).bracketRootValue(false);
@SuppressWarnings("rawtypes")
private static final Map daoPool = new ConcurrentHashMap<>();
private static final Map, BiFunction> sqlAnnoMap = new HashMap<>();
static {
sqlAnnoMap.put(Select.class, (final Annotation anno, final SQLMapper sqlMapper) -> {
final Select tmp = (Select) anno;
int queryTimeout = tmp.queryTimeout();
int fetchSize = tmp.fetchSize();
final boolean isBatch = false;
final int batchSize = -1;
final OP op = tmp.op() == null ? OP.DEFAULT : tmp.op();
final boolean isSingleParameter = tmp.isSingleParameter();
ParsedSql parsedSql = null;
String sql = Strings.stripToEmpty(tmp.sql());
if (Strings.isEmpty(sql)) {
sql = Strings.trim(tmp.value());
}
if (!(Strings.isNotEmpty(sql) ^ Strings.isNotEmpty(tmp.id()))) {
throw new IllegalArgumentException("Sql script and id both are empty or both are not empty: " + Strings.concat(sql, ", ", tmp.id()));
}
if (!Strings.containsWhitespace(sql) && sqlMapper != null && sqlMapper.get(sql) != null) {
sql = sqlMapper.get(sql).getParameterizedSql();
}
final String id = Strings.isNotEmpty(sql) && sqlMapper != null && sqlMapper.get(sql) != null ? sql : tmp.id();
if (Strings.isNotEmpty(id)) {
if (sqlMapper == null || sqlMapper.get(id) == null || Strings.isEmpty(sqlMapper.get(id).getParameterizedSql())) {
throw new IllegalArgumentException("No predefined sql found by id: " + id);
}
parsedSql = sqlMapper.get(id);
sql = parsedSql.getParameterizedSql();
final Map attrs = sqlMapper.getAttrs(id);
if (N.notEmpty(attrs)) {
if (attrs.containsKey(SQLMapper.TIMEOUT)) {
queryTimeout = Numbers.toInt(attrs.get(SQLMapper.TIMEOUT));
}
if (attrs.containsKey(SQLMapper.FETCH_SIZE)) {
fetchSize = Numbers.toInt(attrs.get(SQLMapper.FETCH_SIZE));
}
}
}
return new QueryInfo(sql, parsedSql, queryTimeout, fetchSize, isBatch, batchSize, op, isSingleParameter, tmp.timestamped(), true, false,
tmp.hasDefineWithNamedParameter());
});
sqlAnnoMap.put(Insert.class, (final Annotation anno, final SQLMapper sqlMapper) -> {
final Insert tmp = (Insert) anno;
int queryTimeout = tmp.queryTimeout();
final int fetchSize = -1;
final boolean isBatch = tmp.isBatch();
int batchSize = tmp.batchSize();
final OP op = OP.DEFAULT;
final boolean isSingleParameter = tmp.isSingleParameter();
ParsedSql parsedSql = null;
String sql = Strings.stripToEmpty(tmp.sql());
if (Strings.isEmpty(sql)) {
sql = Strings.trim(tmp.value());
}
if (!(Strings.isNotEmpty(sql) ^ Strings.isNotEmpty(tmp.id()))) {
throw new IllegalArgumentException("Sql script and id both are empty or both are not empty: " + Strings.concat(sql, ", ", tmp.id()));
}
if (!Strings.containsWhitespace(sql) && sqlMapper != null && sqlMapper.get(sql) != null) {
sql = sqlMapper.get(sql).getParameterizedSql();
}
final String id = Strings.isNotEmpty(sql) && sqlMapper != null && sqlMapper.get(sql) != null ? sql : tmp.id();
if (Strings.isNotEmpty(id)) {
if (sqlMapper == null || sqlMapper.get(id) == null || Strings.isEmpty(sqlMapper.get(id).getParameterizedSql())) {
throw new IllegalArgumentException("No predefined sql found by id: " + id);
}
parsedSql = sqlMapper.get(id);
sql = parsedSql.getParameterizedSql();
final Map attrs = sqlMapper.getAttrs(id);
if (N.notEmpty(attrs)) {
if (attrs.containsKey(SQLMapper.TIMEOUT)) {
queryTimeout = Numbers.toInt(attrs.get(SQLMapper.TIMEOUT));
}
if (attrs.containsKey(SQLMapper.BATCH_SIZE)) {
batchSize = Numbers.toInt(attrs.get(SQLMapper.BATCH_SIZE));
}
}
}
return new QueryInfo(sql, parsedSql, queryTimeout, fetchSize, isBatch, batchSize, op, isSingleParameter, tmp.timestamped(), false, false,
tmp.hasDefineWithNamedParameter());
});
sqlAnnoMap.put(Update.class, (final Annotation anno, final SQLMapper sqlMapper) -> {
final Update tmp = (Update) anno;
int queryTimeout = tmp.queryTimeout();
final int fetchSize = -1;
final boolean isBatch = tmp.isBatch();
int batchSize = tmp.batchSize();
final OP op = tmp.op() == null ? OP.update : tmp.op();
final boolean isSingleParameter = tmp.isSingleParameter();
ParsedSql parsedSql = null;
String sql = Strings.stripToEmpty(tmp.sql());
if (Strings.isEmpty(sql)) {
sql = Strings.trim(tmp.value());
}
if (!(Strings.isNotEmpty(sql) ^ Strings.isNotEmpty(tmp.id()))) {
throw new IllegalArgumentException("Sql script and id both are empty or both are not empty: " + Strings.concat(sql, ", ", tmp.id()));
}
if (!Strings.containsWhitespace(sql) && sqlMapper != null && sqlMapper.get(sql) != null) {
sql = sqlMapper.get(sql).getParameterizedSql();
}
final String id = Strings.isNotEmpty(sql) && sqlMapper != null && sqlMapper.get(sql) != null ? sql : tmp.id();
if (Strings.isNotEmpty(id)) {
if (sqlMapper == null || sqlMapper.get(id) == null || Strings.isEmpty(sqlMapper.get(id).getParameterizedSql())) {
throw new IllegalArgumentException("No predefined sql found by id: " + id);
}
parsedSql = sqlMapper.get(id);
sql = parsedSql.getParameterizedSql();
final Map attrs = sqlMapper.getAttrs(id);
if (N.notEmpty(attrs)) {
if (attrs.containsKey(SQLMapper.TIMEOUT)) {
queryTimeout = Numbers.toInt(attrs.get(SQLMapper.TIMEOUT));
}
if (attrs.containsKey(SQLMapper.BATCH_SIZE)) {
batchSize = Numbers.toInt(attrs.get(SQLMapper.BATCH_SIZE));
}
}
}
return new QueryInfo(sql, parsedSql, queryTimeout, fetchSize, isBatch, batchSize, op, isSingleParameter, tmp.timestamped(), false, false,
tmp.hasDefineWithNamedParameter());
});
sqlAnnoMap.put(Delete.class, (final Annotation anno, final SQLMapper sqlMapper) -> {
final Delete tmp = (Delete) anno;
int queryTimeout = tmp.queryTimeout();
final int fetchSize = -1;
final boolean isBatch = tmp.isBatch();
int batchSize = tmp.batchSize();
final OP op = OP.DEFAULT;
final boolean isSingleParameter = tmp.isSingleParameter();
ParsedSql parsedSql = null;
String sql = Strings.stripToEmpty(tmp.sql());
if (Strings.isEmpty(sql)) {
sql = Strings.trim(tmp.value());
}
if (!(Strings.isNotEmpty(sql) ^ Strings.isNotEmpty(tmp.id()))) {
throw new IllegalArgumentException("Sql script and id both are empty or both are not empty: " + Strings.concat(sql, ", ", tmp.id()));
}
if (!Strings.containsWhitespace(sql) && sqlMapper != null && sqlMapper.get(sql) != null) {
sql = sqlMapper.get(sql).getParameterizedSql();
}
final String id = Strings.isNotEmpty(sql) && sqlMapper != null && sqlMapper.get(sql) != null ? sql : tmp.id();
if (Strings.isNotEmpty(id)) {
if (sqlMapper == null || sqlMapper.get(id) == null || Strings.isEmpty(sqlMapper.get(id).getParameterizedSql())) {
throw new IllegalArgumentException("No predefined sql found by id: " + id);
}
parsedSql = sqlMapper.get(id);
sql = parsedSql.getParameterizedSql();
final Map attrs = sqlMapper.getAttrs(id);
if (N.notEmpty(attrs)) {
if (attrs.containsKey(SQLMapper.TIMEOUT)) {
queryTimeout = Numbers.toInt(attrs.get(SQLMapper.TIMEOUT));
}
if (attrs.containsKey(SQLMapper.BATCH_SIZE)) {
batchSize = Numbers.toInt(attrs.get(SQLMapper.BATCH_SIZE));
}
}
}
return new QueryInfo(sql, parsedSql, queryTimeout, fetchSize, isBatch, batchSize, op, isSingleParameter, tmp.timestamped(), false, false,
tmp.hasDefineWithNamedParameter());
});
sqlAnnoMap.put(Call.class, (final Annotation anno, final SQLMapper sqlMapper) -> {
final Call tmp = (Call) anno;
int queryTimeout = tmp.queryTimeout();
final int fetchSize = -1;
final boolean isBatch = false;
final int batchSize = -1;
final OP op = OP.DEFAULT;
final boolean isSingleParameter = tmp.isSingleParameter();
ParsedSql parsedSql = null;
String sql = Strings.stripToEmpty(tmp.sql());
if (Strings.isEmpty(sql)) {
sql = Strings.trim(tmp.value());
}
if (!(Strings.isNotEmpty(sql) ^ Strings.isNotEmpty(tmp.id()))) {
throw new IllegalArgumentException("Sql script and id both are empty or both are not empty: " + Strings.concat(sql, ", ", tmp.id()));
}
if (!Strings.containsWhitespace(sql) && sqlMapper != null && sqlMapper.get(sql) != null) {
sql = sqlMapper.get(sql).getParameterizedSql();
}
final String id = Strings.isNotEmpty(sql) && sqlMapper != null && sqlMapper.get(sql) != null ? sql : tmp.id();
if (Strings.isNotEmpty(id)) {
if (sqlMapper == null || sqlMapper.get(id) == null || Strings.isEmpty(sqlMapper.get(id).getParameterizedSql())) {
throw new IllegalArgumentException("No predefined sql found by id: " + id);
}
parsedSql = sqlMapper.get(id);
sql = parsedSql.getParameterizedSql();
final Map attrs = sqlMapper.getAttrs(id);
if (N.notEmpty(attrs) && attrs.containsKey(SQLMapper.TIMEOUT)) {
queryTimeout = Numbers.toInt(attrs.get(SQLMapper.TIMEOUT));
}
}
return new QueryInfo(sql, parsedSql, queryTimeout, fetchSize, isBatch, batchSize, op, isSingleParameter, false, true, true, false);
});
}
@SuppressWarnings("rawtypes")
private static final Map, Predicate> isValuePresentMap = N.newHashMap(20);
static {
final Map, Predicate>> tmp = N.newHashMap(20);
tmp.put(u.Nullable.class, (final u.Nullable> t) -> t.isPresent());
tmp.put(u.Optional.class, (final u.Optional> t) -> t.isPresent());
tmp.put(u.OptionalBoolean.class, (final u.OptionalBoolean t) -> t.isPresent());
tmp.put(u.OptionalChar.class, (final u.OptionalChar t) -> t.isPresent());
tmp.put(u.OptionalByte.class, (final u.OptionalByte t) -> t.isPresent());
tmp.put(u.OptionalShort.class, (final u.OptionalShort t) -> t.isPresent());
tmp.put(u.OptionalInt.class, (final u.OptionalInt t) -> t.isPresent());
tmp.put(u.OptionalLong.class, (final u.OptionalLong t) -> t.isPresent());
tmp.put(u.OptionalFloat.class, (final u.OptionalFloat t) -> t.isPresent());
tmp.put(u.OptionalDouble.class, (final u.OptionalDouble t) -> t.isPresent());
tmp.put(java.util.Optional.class, (final java.util.Optional> t) -> t.isPresent());
tmp.put(java.util.OptionalInt.class, (final java.util.OptionalInt t) -> t.isPresent());
tmp.put(java.util.OptionalLong.class, (final java.util.OptionalLong t) -> t.isPresent());
tmp.put(java.util.OptionalDouble.class, (final java.util.OptionalDouble t) -> t.isPresent());
isValuePresentMap.putAll(tmp);
}
private static Set> notCacheableTypes = N.asSet(void.class, Void.class, Iterator.class, java.util.stream.BaseStream.class, BaseStream.class,
EntryStream.class, Stream.class, Seq.class);
@SuppressWarnings("rawtypes")
private static Jdbc.BiParametersSetter collParamsSetter = AbstractQuery::setParameters;
private static Jdbc.BiParametersSetter objParamsSetter = (final NamedQuery q, final Object p) -> q.setParameters(p);
/**
* Creates the method handle.
*
* @param method
* @return
*/
private static MethodHandle createMethodHandle(final Method method) {
final Class> declaringClass = method.getDeclaringClass();
try {
return MethodHandles.lookup().in(declaringClass).unreflectSpecial(method, declaringClass);
} catch (final Exception e) {
try {
final Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
ClassUtil.setAccessibleQuietly(constructor, true);
return constructor.newInstance(declaringClass).in(declaringClass).unreflectSpecial(method, declaringClass);
} catch (final Exception ex) {
try {
return MethodHandles.lookup()
.findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
declaringClass);
} catch (final Exception exx) {
throw new UnsupportedOperationException(exx);
}
}
}
}
private static final Set singleQueryPrefix = N.asSet("get", "findFirst", "findOne", "findOnlyOne", "selectFirst", "selectOne", "selectOnlyOne",
"exist", "notExist", "has", "is");
/**
* Checks if is list query.
*
* @param method
* @return {@code true}, if is list query
*/
private static boolean isListQuery(final Method method, final Class> returnType, final OP op, final String fullClassMethodName) {
final String methodName = method.getName();
final Class>[] paramTypes = method.getParameterTypes();
final int paramLen = paramTypes.length;
if (op == OP.list || op == OP.listAll) {
if (Collection.class.equals(returnType) || !(Collection.class.isAssignableFrom(returnType))) {
throw new UnsupportedOperationException(
"The result type of list OP must be sub type of Collection, can't be: " + returnType + " in method: " + fullClassMethodName);
}
return true;
} else if (method.getAnnotation(MappedByKey.class) != null) {
return true;
} else if (op != OP.DEFAULT) {
return false;
}
if (Collection.class.isAssignableFrom(returnType)) {
if (method.getAnnotation(MergedById.class) != null) {
return true;
}
// Check if return type is generic List type.
if (method.getGenericReturnType() instanceof ParameterizedType) {
final ParameterizedType parameterizedReturnType = (ParameterizedType) method.getGenericReturnType();
final Class> paramClassInReturnType = parameterizedReturnType.getActualTypeArguments()[0] instanceof Class
? (Class>) parameterizedReturnType.getActualTypeArguments()[0]
: (Class>) ((ParameterizedType) parameterizedReturnType.getActualTypeArguments()[0]).getRawType();
if (paramLen > 0
&& (Jdbc.RowMapper.class.isAssignableFrom(paramTypes[paramLen - 1])
|| Jdbc.BiRowMapper.class.isAssignableFrom(paramTypes[paramLen - 1]))
&& method.getGenericParameterTypes()[paramLen - 1] instanceof ParameterizedType) {
final ParameterizedType rowMapperType = (ParameterizedType) method.getGenericParameterTypes()[paramLen - 1];
final Class> paramClassInRowMapper = rowMapperType.getActualTypeArguments()[0] instanceof Class
? (Class>) rowMapperType.getActualTypeArguments()[0]
: (Class>) ((ParameterizedType) rowMapperType.getActualTypeArguments()[0]).getRawType();
if (paramClassInReturnType != null && paramClassInRowMapper != null && paramClassInReturnType.isAssignableFrom(paramClassInRowMapper)) {
return true;
} else {
// if the return type of the method is same as the return type of RowMapper/BiRowMapper parameter, return false;
return !parameterizedReturnType.equals(rowMapperType.getActualTypeArguments()[0]);
}
}
}
if (paramLen > 0 && (Jdbc.ResultExtractor.class.isAssignableFrom(paramTypes[paramLen - 1])
|| Jdbc.BiResultExtractor.class.isAssignableFrom(paramTypes[paramLen - 1]))) {
return false;
}
return singleQueryPrefix.stream()
.noneMatch(
it -> methodName.startsWith(it) && (methodName.length() == it.length() || Character.isUpperCase(methodName.charAt(it.length()))));
} else {
return false;
}
}
private static boolean isExistsQuery(final Method method, final OP op, final String fullClassMethodName) {
final String methodName = method.getName();
final Class>[] paramTypes = method.getParameterTypes();
final Class> returnType = method.getReturnType();
final int paramLen = paramTypes.length;
if (op == OP.exists) {
if (!(boolean.class.equals(returnType) || Boolean.class.equals(returnType))) {
throw new UnsupportedOperationException(
"The result type of exists OP must be boolean or Boolean, can't be: " + returnType + " in method: " + fullClassMethodName);
}
return true;
} else if (op != OP.DEFAULT) {
return false;
}
if (paramLen > 0 //
&& (Jdbc.ResultExtractor.class.isAssignableFrom(paramTypes[paramLen - 1]) //
|| Jdbc.BiResultExtractor.class.isAssignableFrom(paramTypes[paramLen - 1]) //
|| Jdbc.RowMapper.class.isAssignableFrom(paramTypes[paramLen - 1]) //
|| Jdbc.BiRowMapper.class.isAssignableFrom(paramTypes[paramLen - 1]))) {
return false;
}
return (boolean.class.equals(returnType) || Boolean.class.equals(returnType))
&& ((methodName.startsWith("exists") && (methodName.length() == 6 || Character.isUpperCase(methodName.charAt(6))))
|| (methodName.startsWith("exist") && (methodName.length() == 5 || Character.isUpperCase(methodName.charAt(5))))
|| (methodName.startsWith("notExists") && (methodName.length() == 9 || Character.isUpperCase(methodName.charAt(9))))
|| (methodName.startsWith("notExist") && (methodName.length() == 8 || Character.isUpperCase(methodName.charAt(8)))));
}
private static boolean isFindFirst(final Method method, final OP op) {
if (op == OP.findFirst) {
return true;
}
return op == OP.DEFAULT && !(method.getName().startsWith("findOnlyOne") || method.getName().startsWith("queryForSingle")
|| method.getName().startsWith("queryForUnique"));
}
private static boolean isFindOnlyOne(final Method method, final OP op) {
if (op == OP.findOnlyOne) {
return true;
}
return op == OP.DEFAULT && method.getName().startsWith("findOnlyOne");
}
private static boolean isQueryForUnique(final Method method, final OP op) {
if (op == OP.queryForUnique) {
return true;
}
return op == OP.DEFAULT && method.getName().startsWith("queryForUnique");
}
private static final ImmutableSet> singleReturnTypeSet = ImmutableSet.of(u.Nullable.class, u.Optional.class, u.OptionalBoolean.class,
u.OptionalChar.class, u.OptionalByte.class, u.OptionalShort.class, u.OptionalInt.class, u.OptionalLong.class, u.OptionalDouble.class,
java.util.Optional.class, java.util.OptionalInt.class, java.util.OptionalLong.class, java.util.OptionalDouble.class);
private static boolean isSingleReturnType(final Class> returnType) {
return singleReturnTypeSet.contains(returnType) || ClassUtil.isPrimitiveType(ClassUtil.unwrap(returnType));
}
@SuppressWarnings("rawtypes")
private static Throwables.BiFunction createSingleQueryFunction(final Class> returnType) {
if (u.OptionalBoolean.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForBoolean();
} else if (u.OptionalChar.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForChar();
} else if (u.OptionalByte.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForByte();
} else if (u.OptionalShort.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForShort();
} else if (u.OptionalInt.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForInt();
} else if (u.OptionalLong.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForLong();
} else if (u.OptionalFloat.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForFloat();
} else if (u.OptionalDouble.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForDouble();
} else if (u.Optional.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleNonNull(returnType);
} else if (u.Nullable.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleResult(returnType);
} else {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleResult(returnType).orElse(N.defaultValueOf(returnType));
}
}
@SuppressWarnings("rawtypes")
private static Throwables.BiFunction createQueryFunctionByMethod(final Class> entityClass,
final Method method, final String mappedByKey, final List mergedByIds, final Map prefixFieldMap,
final boolean fetchColumnByEntityClass, final boolean hasRowMapperOrExtractor, final boolean hasRowFilter, final OP op, final boolean isCall,
final String fullClassMethodName) {
final Class>[] paramTypes = method.getParameterTypes();
final Class> returnType = method.getReturnType();
final Class> firstReturnEleType = getFirstReturnEleType(method);
final Class> secondReturnEleType = getSecondReturnEleType(method);
final Class> firstReturnEleEleType = getFirstReturnEleEleType(method);
final int paramLen = paramTypes.length;
final Class> lastParamType = paramLen == 0 ? null : paramTypes[paramLen - 1];
final boolean isListQuery = isListQuery(method, returnType, op, fullClassMethodName);
final boolean isExists = isExistsQuery(method, op, fullClassMethodName);
if ((op == OP.stream && !Stream.class.isAssignableFrom(returnType))
|| (op == OP.query && !(DataSet.class.isAssignableFrom(returnType) || lastParamType == null
|| Jdbc.ResultExtractor.class.isAssignableFrom(lastParamType) || Jdbc.BiResultExtractor.class.isAssignableFrom(lastParamType)))) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if ((op == OP.findFirst || op == OP.findOnlyOne) && Nullable.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if ((op == OP.executeAndGetOutParameters && !returnType.isAssignableFrom(Jdbc.OutParamResult.class))
|| (Stream.class.isAssignableFrom(returnType) && !(op == OP.stream || op == OP.DEFAULT))) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (DataSet.class.isAssignableFrom(returnType) && !(op == OP.query || op == OP.DEFAULT)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if ((u.Optional.class.isAssignableFrom(returnType) || java.util.Optional.class.isAssignableFrom(returnType))
&& !(op == OP.findFirst || op == OP.findOnlyOne || op == OP.queryForSingle || op == OP.queryForUnique || op == OP.DEFAULT)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (Nullable.class.isAssignableFrom(returnType) && !(op == OP.queryForSingle || op == OP.queryForUnique || op == OP.DEFAULT)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (isCall) {
if (op == OP.executeAndGetOutParameters) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).executeAndGetOutParameters();
} else if (op == OP.listAll) {
if (Tuple2.class.isAssignableFrom(returnType)) {
if (firstReturnEleType == null || !List.class.isAssignableFrom(firstReturnEleType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (hasRowMapperOrExtractor) {
if (Jdbc.RowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery)
.listAllResultsetsAndGetOutParameters((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery,
args) -> (R) ((CallableQuery) preparedQuery).listAllResultsetsAndGetOutParameters((Jdbc.RowMapper) args[paramLen - 1]);
}
} else if (Jdbc.BiRowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery)
.listAllResultsetsAndGetOutParameters((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery)
.listAllResultsetsAndGetOutParameters((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleEleType == null) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsetsAndGetOutParameters(firstReturnEleEleType);
}
} else {
if (!List.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (hasRowMapperOrExtractor) {
if (Jdbc.RowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsets((Jdbc.RowFilter) args[paramLen - 2],
(Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsets((Jdbc.RowMapper) args[paramLen - 1]);
}
} else if (Jdbc.BiRowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsets((Jdbc.BiRowFilter) args[paramLen - 2],
(Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsets((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleType == null) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAllResultsets(firstReturnEleType);
}
}
} else if (op == OP.queryAll) {
if (Tuple2.class.isAssignableFrom(returnType)) {
if (firstReturnEleType == null || !List.class.isAssignableFrom(firstReturnEleType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (hasRowMapperOrExtractor) {
if (Jdbc.ResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery)
.queryAllResultsetsAndGetOutParameters((Jdbc.ResultExtractor) args[paramLen - 1]);
} else if (Jdbc.BiResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery)
.queryAllResultsetsAndGetOutParameters((Jdbc.BiResultExtractor) args[paramLen - 1]);
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleEleType == null || !DataSet.class.isAssignableFrom(firstReturnEleEleType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAllResultsetsAndGetOutParameters();
}
} else {
if (!List.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (hasRowMapperOrExtractor) {
if (Jdbc.ResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAllResultsets((Jdbc.ResultExtractor) args[paramLen - 1]);
} else if (Jdbc.BiResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAllResultsets((Jdbc.BiResultExtractor) args[paramLen - 1]);
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleType == null || !DataSet.class.isAssignableFrom(firstReturnEleType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAllResultsets();
}
}
} else if (op == OP.streamAll) {
if (!Stream.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (hasRowMapperOrExtractor) {
if (Jdbc.RowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).streamAllResultsets((Jdbc.RowFilter) args[paramLen - 2],
(Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).streamAllResultsets((Jdbc.RowMapper) args[paramLen - 1]);
}
} else if (Jdbc.BiRowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).streamAllResultsets((Jdbc.BiRowFilter) args[paramLen - 2],
(Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).streamAllResultsets((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleType == null) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).streamAllResultsets(firstReturnEleType);
}
}
if (Tuple2.class.isAssignableFrom(returnType) && (op == OP.list || op == OP.query || op == OP.DEFAULT)) {
// if (firstReturnEleType == null || !List.class.isAssignableFrom(firstReturnEleType)) {
// throw new UnsupportedOperationException(
// "The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
// }
if (hasRowMapperOrExtractor) {
if (Jdbc.RowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAndGetOutParameters((Jdbc.RowFilter) args[paramLen - 2],
(Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAndGetOutParameters((Jdbc.RowMapper) args[paramLen - 1]);
}
} else if (Jdbc.BiRowMapper.class.isAssignableFrom(lastParamType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAndGetOutParameters((Jdbc.BiRowFilter) args[paramLen - 2],
(Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAndGetOutParameters((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else if (Jdbc.ResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAndGetOutParameters((Jdbc.ResultExtractor) args[paramLen - 1]);
} else if (Jdbc.BiResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery,
args) -> (R) ((CallableQuery) preparedQuery).queryAndGetOutParameters((Jdbc.BiResultExtractor) args[paramLen - 1]);
} else {
throw new UnsupportedOperationException("The last parameter type: " + lastParamType + " of method: " + fullClassMethodName
+ " is not supported the specified op: " + op);
}
} else {
if (firstReturnEleType == null) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
if (DataSet.class.isAssignableFrom(firstReturnEleType)) {
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).queryAndGetOutParameters();
}
if (firstReturnEleEleType == null) {
throw new UnsupportedOperationException(
"The return type: " + returnType + " of method: " + fullClassMethodName + " is not supported the specified op: " + op);
}
return (preparedQuery, args) -> (R) ((CallableQuery) preparedQuery).listAndGetOutParameters(firstReturnEleEleType);
}
}
}
final MappedByKey mappedBykeyAnno = method.getAnnotation(MappedByKey.class);
final Class extends Map> targetMapClass = Strings.isEmpty(mappedByKey) ? null : mappedBykeyAnno.mapClass();
if (hasRowMapperOrExtractor) {
if (Strings.isNotEmpty(mappedByKey) || N.notEmpty(mergedByIds) || N.notEmpty(prefixFieldMap)) {
throw new UnsupportedOperationException(
"RowMapper/ResultExtractor is not supported by method annotated with @MappedBykey/@MergedById/@PrefixFieldMapping: "
+ fullClassMethodName);
}
if (!(op == OP.findFirst || op == OP.findOnlyOne || op == OP.list || op == OP.listAll || op == OP.query || op == OP.queryAll || op == OP.stream
|| op == OP.streamAll || op == OP.DEFAULT)) {
throw new UnsupportedOperationException("RowMapper/ResultExtractor is not supported by OP: " + op + " in method: " + fullClassMethodName);
}
if (hasRowFilter && (op == OP.findFirst || op == OP.findOnlyOne || op == OP.list || op == OP.listAll || op == OP.query || op == OP.queryAll
|| op == OP.stream || op == OP.streamAll || op == OP.DEFAULT)) {
throw new UnsupportedOperationException("RowFilter is not supported by OP: " + op + " in method: " + fullClassMethodName);
}
if (Jdbc.RowMapper.class.isAssignableFrom(lastParamType)) {
if (isListQuery) {
if (returnType.equals(List.class)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) preparedQuery.list((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) preparedQuery.list((Jdbc.RowMapper) args[paramLen - 1]);
}
} else {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1])
.toCollection(Suppliers.ofCollection((Class) returnType));
} else {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.RowMapper) args[paramLen - 1])
.toCollection(Suppliers.ofCollection((Class) returnType));
}
}
} else if (u.Optional.class.isAssignableFrom(returnType)) {
if (isFindOnlyOne(method, op)) {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1]).onlyOne();
} else {
return (preparedQuery, args) -> (R) preparedQuery.findOnlyOne((Jdbc.RowMapper) args[paramLen - 1]);
}
} else {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1]).first();
} else {
return (preparedQuery, args) -> (R) preparedQuery.findFirst((Jdbc.RowMapper) args[paramLen - 1]);
}
}
} else if (Stream.class.isAssignableFrom(returnType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2], (Jdbc.RowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.RowMapper) args[paramLen - 1]);
}
} else {
if (Nullable.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type of method: " + method.getName() + " can't be: " + returnType + " when RowMapper/BiRowMapper is specified");
}
if (isFindOnlyOne(method, op)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((Stream) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2],
(Jdbc.RowMapper) args[paramLen - 1])).onlyOne().orElse(N.defaultValueOf(returnType));
} else {
return (preparedQuery,
args) -> (R) preparedQuery.findOnlyOne((Jdbc.RowMapper) args[paramLen - 1]).orElse(N.defaultValueOf(returnType));
}
} else {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((Stream) preparedQuery.stream((Jdbc.RowFilter) args[paramLen - 2],
(Jdbc.RowMapper) args[paramLen - 1])).first().orElse(N.defaultValueOf(returnType));
} else {
return (preparedQuery,
args) -> (R) preparedQuery.findFirst((Jdbc.RowMapper) args[paramLen - 1]).orElse(N.defaultValueOf(returnType));
}
}
}
} else if (Jdbc.BiRowMapper.class.isAssignableFrom(lastParamType)) {
if (isListQuery) {
if (returnType.equals(List.class)) {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.list((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) preparedQuery.list((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1])
.toCollection(Suppliers.ofCollection((Class) returnType));
} else {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.BiRowMapper) args[paramLen - 1])
.toCollection(Suppliers.ofCollection((Class) returnType));
}
}
} else if (u.Optional.class.isAssignableFrom(returnType)) {
if (isFindOnlyOne(method, op)) {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1]).onlyOne();
} else {
return (preparedQuery, args) -> (R) preparedQuery.findOnlyOne((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
if (hasRowFilter) {
return (preparedQuery,
args) -> (R) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1]).first();
} else {
return (preparedQuery, args) -> (R) preparedQuery.findFirst((Jdbc.BiRowMapper) args[paramLen - 1]);
}
}
} else if (Stream.class.isAssignableFrom(returnType)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2], (Jdbc.BiRowMapper) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) preparedQuery.stream((Jdbc.BiRowMapper) args[paramLen - 1]);
}
} else {
if (Nullable.class.isAssignableFrom(returnType)) {
throw new UnsupportedOperationException(
"The return type of method: " + method.getName() + " can't be: " + returnType + " when RowMapper/BiRowMapper is specified");
}
if (isFindOnlyOne(method, op)) {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((Stream) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2],
(Jdbc.BiRowMapper) args[paramLen - 1])).onlyOne().orElse(N.defaultValueOf(returnType));
} else {
return (preparedQuery,
args) -> (R) preparedQuery.findOnlyOne((Jdbc.BiRowMapper) args[paramLen - 1]).orElse(N.defaultValueOf(returnType));
}
} else {
if (hasRowFilter) {
return (preparedQuery, args) -> (R) ((Stream) preparedQuery.stream((Jdbc.BiRowFilter) args[paramLen - 2],
(Jdbc.BiRowMapper) args[paramLen - 1])).first().orElse(N.defaultValueOf(returnType));
} else {
return (preparedQuery,
args) -> (R) preparedQuery.findFirst((Jdbc.BiRowMapper) args[paramLen - 1]).orElse(N.defaultValueOf(returnType));
}
}
}
} else {
if (!(op == OP.query || op == OP.DEFAULT)) {
throw new UnsupportedOperationException(
"ResultExtractor/BiResultExtractor is not supported by OP: " + op + " in method: " + fullClassMethodName);
}
if (method.getGenericParameterTypes()[paramLen - 1] instanceof ParameterizedType) {
final java.lang.reflect.Type resultExtractorReturnType = ((ParameterizedType) method.getGenericParameterTypes()[paramLen - 1])
.getActualTypeArguments()[0];
final Class> resultExtractorReturnClass = resultExtractorReturnType instanceof Class ? (Class>) resultExtractorReturnType
: (Class>) ((ParameterizedType) resultExtractorReturnType).getRawType();
if (returnType.isAssignableFrom(resultExtractorReturnClass)) {
throw new UnsupportedOperationException("The return type: " + returnType + " of method: " + method.getName()
+ " is not assignable from the return type of ResultExtractor: " + resultExtractorReturnClass);
}
}
if (Jdbc.ResultExtractor.class.isAssignableFrom(lastParamType)) {
return (preparedQuery, args) -> (R) preparedQuery.query((Jdbc.ResultExtractor) args[paramLen - 1]);
} else {
return (preparedQuery, args) -> (R) preparedQuery.query((Jdbc.BiResultExtractor) args[paramLen - 1]);
}
}
} else if (Strings.isNotEmpty(mappedByKey)) {
final Class> targetEntityClass = secondReturnEleType == null || !ClassUtil.isBeanClass(secondReturnEleType) ? entityClass : secondReturnEleType;
final BeanInfo entityInfo = ParserUtil.getBeanInfo(targetEntityClass);
final PropInfo propInfo = entityInfo.getPropInfo(mappedByKey);
final Function keyExtractor = propInfo::getPropValue;
final List mergedByKey = N.isEmpty(mergedByIds) ? N.asList(mappedByKey) : mergedByIds;
return (preparedQuery, args) -> {
final DataSet dataSet = (DataSet) preparedQuery.query(Jdbc.ResultExtractor.toDataSet(targetEntityClass, prefixFieldMap));
final List entities = dataSet.toMergedEntities(mergedByKey, dataSet.columnNameList(), prefixFieldMap, targetEntityClass);
return (R) Stream.of(entities).toMap(keyExtractor, Fn.identity(), Suppliers.ofMap(targetMapClass));
};
} else if (N.notEmpty(mergedByIds)) {
if (returnType.isAssignableFrom(Collection.class) || returnType.isAssignableFrom(u.Optional.class)
|| returnType.isAssignableFrom(java.util.Optional.class)) {
final Class> targetEntityClass = firstReturnEleType == null || !ClassUtil.isBeanClass(firstReturnEleType) ? entityClass : firstReturnEleType;
ParserUtil.getBeanInfo(targetEntityClass);
final boolean isCollection = returnType.isAssignableFrom(Collection.class);
final boolean isJavaOption = returnType.isAssignableFrom(java.util.Optional.class);
return (preparedQuery, args) -> {
final DataSet dataSet = (DataSet) preparedQuery.query(Jdbc.ResultExtractor.toDataSet(targetEntityClass, prefixFieldMap));
final List mergedEntities = dataSet.toMergedEntities(mergedByIds, dataSet.columnNameList(), prefixFieldMap, targetEntityClass);
if (isCollection) {
if (returnType.isAssignableFrom(mergedEntities.getClass())) {
return (R) mergedEntities;
} else {
final Collection c = N.newCollection((Class) returnType);
c.addAll(mergedEntities);
return (R) c;
}
} else {
if (isFindOnlyOne(method, op) && N.size(mergedEntities) > 1) {
throw new DuplicatedResultException("More than one record found by the query defined or generated in method: " + method.getName());
}
if (isJavaOption) {
return (R) java.util.Optional.ofNullable(N.firstOrNullIfEmpty(mergedEntities));
} else {
return (R) N.firstNonNull(mergedEntities);
}
}
};
} else {
throw new UnsupportedOperationException("The return type: " + returnType + " of method: " + method.getName()
+ " is not supported by method annotated with @MergedById. Only Optional/List/Collection are supported at present");
}
} else if (isExists) {
if (method.getName().startsWith("not")) {
return (preparedQuery, args) -> (R) (Boolean) preparedQuery.notExists();
} else {
return (preparedQuery, args) -> (R) (Boolean) preparedQuery.exists();
}
} else if (isListQuery) {
if (returnType.equals(List.class)) {
return (preparedQuery, args) -> (R) preparedQuery.list(BiRowMapper.to(firstReturnEleType, prefixFieldMap));
} else {
return (preparedQuery, args) -> (R) preparedQuery.stream(BiRowMapper.to(firstReturnEleType, prefixFieldMap))
.toCollection(Suppliers.ofCollection((Class) returnType));
}
} else if (DataSet.class.isAssignableFrom(returnType)) {
if (fetchColumnByEntityClass) {
return (preparedQuery, args) -> (R) preparedQuery.query(Jdbc.ResultExtractor.toDataSet(entityClass, prefixFieldMap));
} else {
return (preparedQuery, args) -> (R) preparedQuery.query();
}
} else if (Stream.class.isAssignableFrom(returnType)) {
return (preparedQuery, args) -> (R) preparedQuery.stream(BiRowMapper.to(firstReturnEleType, prefixFieldMap));
} else if (u.Optional.class.isAssignableFrom(returnType) || java.util.Optional.class.isAssignableFrom(returnType)
|| Nullable.class.isAssignableFrom(returnType)) {
if (Nullable.class.isAssignableFrom(returnType)) {
if (isQueryForUnique(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForUniqueResult(firstReturnEleType);
} else {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleResult(firstReturnEleType);
}
} else if (u.Optional.class.isAssignableFrom(returnType)) {
if (isFindFirst(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.findFirst(BiRowMapper.to(firstReturnEleType, prefixFieldMap));
} else if (isFindOnlyOne(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.findOnlyOne(BiRowMapper.to(firstReturnEleType, prefixFieldMap));
} else if (isQueryForUnique(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForUniqueNonNull(firstReturnEleType);
} else {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleNonNull(firstReturnEleType);
}
} else if (java.util.Optional.class.isAssignableFrom(returnType)) {
if (isFindFirst(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.findFirst(BiRowMapper.to(firstReturnEleType, prefixFieldMap)).toJdkOptional();
} else if (isFindOnlyOne(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.findOnlyOne(BiRowMapper.to(firstReturnEleType, prefixFieldMap)).toJdkOptional();
} else if (isQueryForUnique(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.queryForUniqueNonNull(firstReturnEleType).toJdkOptional();
} else {
return (preparedQuery, args) -> (R) preparedQuery.queryForSingleNonNull(firstReturnEleType).toJdkOptional();
}
} else {
throw new UnsupportedOperationException("The return type: " + returnType + " of method: " + method.getName() + " is not supported at present");
}
} else {
if (isFindOrListTargetClass(returnType)) {
if (isFindOnlyOne(method, op)) {
return (preparedQuery, args) -> (R) preparedQuery.findOnlyOne(Jdbc.BiRowMapper.to(returnType, prefixFieldMap)).orElseNull();
} else {
return (preparedQuery, args) -> (R) preparedQuery.findFirst(Jdbc.BiRowMapper.to(returnType, prefixFieldMap)).orElseNull();
}
} else {
return createSingleQueryFunction(returnType);
}
}
}
private static boolean isFindOrListTargetClass(final Class> cls) {
return ClassUtil.isBeanClass(cls) || Map.class.isAssignableFrom(cls) || List.class.isAssignableFrom(cls) || Object[].class.isAssignableFrom(cls)
|| ClassUtil.isRecordClass(cls);
}
private static Class> getFirstReturnEleType(final Method method) {
final java.lang.reflect.Type genericReturnType = method.getGenericReturnType();
final ParameterizedType parameterizedReturnType = genericReturnType instanceof ParameterizedType ? (ParameterizedType) genericReturnType : null;
final java.lang.reflect.Type firstActualTypeArgument = parameterizedReturnType == null || N.isEmpty(parameterizedReturnType.getActualTypeArguments())
? null
: parameterizedReturnType.getActualTypeArguments()[0];
return firstActualTypeArgument == null ? null
: (firstActualTypeArgument instanceof Class ? (Class>) firstActualTypeArgument
: (firstActualTypeArgument instanceof ParameterizedType && ((ParameterizedType) firstActualTypeArgument).getRawType() instanceof Class
? (Class>) ((ParameterizedType) firstActualTypeArgument).getRawType()
: null));
}
private static Class> getSecondReturnEleType(final Method method) {
final java.lang.reflect.Type genericReturnType = method.getGenericReturnType();
final ParameterizedType parameterizedReturnType = genericReturnType instanceof ParameterizedType ? (ParameterizedType) genericReturnType : null;
final java.lang.reflect.Type secondActualTypeArgument = parameterizedReturnType == null || N.len(parameterizedReturnType.getActualTypeArguments()) < 2
? null
: parameterizedReturnType.getActualTypeArguments()[1];
return secondActualTypeArgument == null ? null
: (secondActualTypeArgument instanceof Class ? (Class>) secondActualTypeArgument
: (secondActualTypeArgument instanceof ParameterizedType && ((ParameterizedType) secondActualTypeArgument).getRawType() instanceof Class
? (Class>) ((ParameterizedType) secondActualTypeArgument).getRawType()
: null));
}
private static Class> getFirstReturnEleEleType(final Method method) {
final java.lang.reflect.Type genericReturnType = method.getGenericReturnType();
final ParameterizedType parameterizedReturnType = genericReturnType instanceof ParameterizedType ? (ParameterizedType) genericReturnType : null;
final java.lang.reflect.Type firstActualTypeArgument = parameterizedReturnType == null || N.isEmpty(parameterizedReturnType.getActualTypeArguments())
? null
: parameterizedReturnType.getActualTypeArguments()[0];
if (!(firstActualTypeArgument instanceof ParameterizedType) || N.isEmpty(((ParameterizedType) firstActualTypeArgument).getActualTypeArguments())) {
return null;
}
final java.lang.reflect.Type firstReturnEleEleType = ((ParameterizedType) firstActualTypeArgument).getActualTypeArguments()[0];
return firstReturnEleEleType == null ? null
: (firstReturnEleEleType instanceof Class ? (Class>) firstReturnEleEleType
: (firstReturnEleEleType instanceof ParameterizedType && ((ParameterizedType) firstReturnEleEleType).getRawType() instanceof Class
? (Class>) ((ParameterizedType) firstReturnEleEleType).getRawType()
: null));
}
@SuppressWarnings("rawtypes")
private static Jdbc.BiParametersSetter createParametersSetter(final QueryInfo queryInfo, final String fullClassMethodName,
final Method method, final Class>[] paramTypes, final int paramLen, final int defineParamLen, final int[] stmtParamIndexes,
final boolean[] bindListParamFlags, final int stmtParamLen) {
Jdbc.BiParametersSetter parametersSetter = null;
boolean hasParameterSetter = true;
if (paramLen - defineParamLen > 0 && Jdbc.ParametersSetter.class.isAssignableFrom(paramTypes[defineParamLen])) {
parametersSetter = (preparedQuery, args) -> preparedQuery.settParameters((Jdbc.ParametersSetter) args[defineParamLen]);
} else if (paramLen - defineParamLen > 1 && Jdbc.BiParametersSetter.class.isAssignableFrom(paramTypes[defineParamLen + 1])) {
parametersSetter = (preparedQuery, args) -> preparedQuery.settParameters(args[defineParamLen], (Jdbc.BiParametersSetter) args[defineParamLen + 1]);
} else if (paramLen - defineParamLen > 1 && Jdbc.TriParametersSetter.class.isAssignableFrom(paramTypes[defineParamLen + 1])) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setParameters(args[defineParamLen],
(Jdbc.TriParametersSetter) args[defineParamLen + 1]);
} else {
hasParameterSetter = false;
}
if (hasParameterSetter) {
throw new UnsupportedOperationException(
"Setting parameters by 'ParametersSetter/BiParametersSetter/TriParametersSetter' is not enabled at present. Can't use it in method: "
+ fullClassMethodName);
}
if (parametersSetter != null || stmtParamLen == 0 || queryInfo.isBatch) { //NOSONAR
// ignore
} else if (stmtParamLen == 1) {
final Class> paramTypeOne = paramTypes[stmtParamIndexes[0]];
if (queryInfo.isCall) {
final String paramName = StreamEx.of(method.getParameterAnnotations()[stmtParamIndexes[0]])
.select(Bind.class)
.map(Bind::value)
.first()
.orElseNull();
if (Strings.isNotEmpty(paramName)) {
parametersSetter = (preparedQuery, args) -> ((CallableQuery) preparedQuery).setObject(paramName, args[stmtParamIndexes[0]]);
} else if (queryInfo.isSingleParameter) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setObject(1, args[stmtParamIndexes[0]]);
} else if (Map.class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> ((CallableQuery) preparedQuery).setParameters((Map) args[stmtParamIndexes[0]]);
} else if (ClassUtil.isBeanClass(paramTypeOne) || EntityId.class.isAssignableFrom(paramTypeOne) || ClassUtil.isRecordClass(paramTypeOne)) {
throw new UnsupportedOperationException("In method: " + fullClassMethodName
+ ", parameters for call(procedure) have to be binded with names through annotation @Bind, or Map. Entity/EntityId type parameter are not supported");
} else if (Collection.class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setParameters((Collection) args[stmtParamIndexes[0]]);
} else if (Object[].class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setParameters((Object[]) args[stmtParamIndexes[0]]);
} else {
parametersSetter = (preparedQuery, args) -> preparedQuery.setObject(1, args[stmtParamIndexes[0]]);
}
} else if (queryInfo.isNamedQuery) {
final String paramName = StreamEx.of(method.getParameterAnnotations()[stmtParamIndexes[0]])
.select(Bind.class)
.map(Bind::value)
.first()
.orElseNull();
if (Strings.isNotEmpty(paramName)) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setObject(paramName, args[stmtParamIndexes[0]]);
} else if (queryInfo.isSingleParameter) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setObject(1, args[stmtParamIndexes[0]]);
} else if (ClassUtil.isBeanClass(paramTypeOne) || ClassUtil.isRecordClass(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setParameters(args[stmtParamIndexes[0]]);
} else if (Map.class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setParameters((Map) args[stmtParamIndexes[0]]);
} else if (EntityId.class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setParameters((EntityId) args[stmtParamIndexes[0]]);
} else {
throw new UnsupportedOperationException("In method: " + fullClassMethodName
+ ", parameters for named query have to be binded with names through annotation @Bind, or Map/Entity with getter/setter methods. Can not be: "
+ ClassUtil.getSimpleClassName(paramTypeOne));
}
} else {
if (bindListParamFlags[0]) {
parametersSetter = (preparedQuery, args) -> {
final Object paramOne = args[stmtParamIndexes[0]];
int idx = 1;
if (paramOne instanceof Collection) {
for (final Object e : (Collection) paramOne) {
preparedQuery.setObject(idx++, e);
}
} else if (paramOne instanceof int[]) {
for (final int e : (int[]) paramOne) {
preparedQuery.setInt(idx++, e);
}
} else if (paramOne instanceof long[]) {
for (final long e : (long[]) paramOne) {
preparedQuery.setLong(idx++, e);
}
} else if (paramOne instanceof double[]) {
for (final double e : (double[]) paramOne) {
preparedQuery.setDouble(idx++, e);
}
} else if (paramOne instanceof String[]) {
for (final String e : (String[]) paramOne) {
preparedQuery.setString(idx++, e);
}
} else if (paramOne instanceof Object[]) {
for (final Object e : (Object[]) paramOne) {
preparedQuery.setObject(idx++, e);
}
} else if (paramOne != null) {
for (int j = 0, len = Array.getLength(paramOne); j < len; j++) {
preparedQuery.setObject(idx++, Array.get(paramOne, j));
}
}
};
} else if (queryInfo.isSingleParameter) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setObject(1, args[stmtParamIndexes[0]]);
} else if (Collection.class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setParameters((Collection) args[stmtParamIndexes[0]]);
} else if (Object[].class.isAssignableFrom(paramTypeOne)) {
parametersSetter = (preparedQuery, args) -> preparedQuery.setParameters((Object[]) args[stmtParamIndexes[0]]);
} else {
parametersSetter = (preparedQuery, args) -> preparedQuery.setObject(1, args[stmtParamIndexes[0]]);
}
}
} else {
if (queryInfo.isCall) {
@SuppressWarnings("resource")
final String[] paramNames = IntStreamEx.of(stmtParamIndexes)
.mapToObj(i -> StreamEx.of(method.getParameterAnnotations()[i]).select(Bind.class).first().orElse(null))
.skipNulls()
.map(Bind::value)
.toArray(IntFunctions.ofStringArray());
if (N.notEmpty(paramNames)) {
parametersSetter = (preparedQuery, args) -> {
final CallableQuery namedQuery = ((CallableQuery) preparedQuery);
for (int i = 0; i < stmtParamLen; i++) {
namedQuery.setObject(paramNames[i], args[stmtParamIndexes[i]]);
}
};
} else {
if (stmtParamLen == paramLen) {
parametersSetter = AbstractQuery::setParameters;
} else {
parametersSetter = (preparedQuery, args) -> {
for (int i = 0; i < stmtParamLen; i++) {
preparedQuery.setObject(i + 1, args[stmtParamIndexes[i]]);
}
};
}
}
} else if (queryInfo.isNamedQuery) {
@SuppressWarnings("resource")
final String[] paramNames = IntStreamEx.of(stmtParamIndexes)
.mapToObj(i -> StreamEx.of(method.getParameterAnnotations()[i])
.select(Bind.class)
.first()
.orElseThrow(() -> new UnsupportedOperationException("In method: " + fullClassMethodName + ", parameters[" + i + "]: "
+ ClassUtil.getSimpleClassName(method.getParameterTypes()[i])
+ " is not binded with parameter named through annotation @Bind")))
.map(Bind::value)
.toArray(IntFunctions.ofStringArray());
final List diffParamNames = N.difference(queryInfo.parsedSql.getNamedParameters(), N.asList(paramNames));
if (N.notEmpty(diffParamNames) && (diffParamNames.size() > 1 || (diffParamNames.size() == 1 && !diffParamNames.contains(PN_NOW)))) {
throw new UnsupportedOperationException("In method: " + fullClassMethodName
+ ", The named parameters in sql are different from the names binded by method parameters: " + diffParamNames);
}
parametersSetter = (preparedQuery, args) -> {
final NamedQuery namedQuery = ((NamedQuery) preparedQuery);
for (int i = 0; i < stmtParamLen; i++) {
namedQuery.setObject(paramNames[i], args[stmtParamIndexes[i]]);
}
};
} else {
if (stmtParamLen == paramLen && StreamEx.of(bindListParamFlags).allMatch(it -> !it)) {
parametersSetter = AbstractQuery::setParameters;
} else {
parametersSetter = (preparedQuery, args) -> {
for (int idx = 1, i = 0; i < stmtParamLen; i++) {
if (bindListParamFlags[i]) {
final Object paramOne = args[stmtParamIndexes[i]];
if (paramOne instanceof Collection) {
for (final Object e : (Collection) paramOne) {
preparedQuery.setObject(idx++, e);
}
} else if (paramOne instanceof int[]) {
for (final int e : (int[]) paramOne) {
preparedQuery.setInt(idx++, e);
}
} else if (paramOne instanceof long[]) {
for (final long e : (long[]) paramOne) {
preparedQuery.setLong(idx++, e);
}
} else if (paramOne instanceof String[]) {
for (final String e : (String[]) paramOne) {
preparedQuery.setString(idx++, e);
}
} else if (paramOne instanceof Object[]) {
for (final Object e : (Object[]) paramOne) {
preparedQuery.setObject(idx++, e);
}
} else if (paramOne != null) {
for (int j = 0, len = Array.getLength(paramOne); j < len; j++) {
preparedQuery.setObject(idx++, Array.get(paramOne, j));
}
}
} else {
preparedQuery.setObject(idx++, args[stmtParamIndexes[i]]);
}
}
};
}
}
}
if (queryInfo.isNamedQuery && queryInfo.timestamped && queryInfo.parsedSql.getNamedParameters().contains(PN_NOW)) {
if (parametersSetter == null) {
parametersSetter = (preparedQuery, args) -> ((NamedQuery) preparedQuery).setTimestamp(PN_NOW, Dates.currentTimestamp());
} else {
final BiParametersSetter tmp = parametersSetter;
parametersSetter = (preparedQuery, args) -> {
tmp.accept(preparedQuery, args);
((NamedQuery) preparedQuery).setTimestamp(PN_NOW, Dates.currentTimestamp());
};
}
}
return parametersSetter == null ? Jdbc.BiParametersSetter.DO_NOTHING : parametersSetter;
}
@SuppressWarnings({ "rawtypes", "unused" })
private static AbstractQuery prepareQuery(final Dao proxy, final QueryInfo queryInfo, final MergedById mergedByIdAnno, final String fullClassMethodName,
final Method method, final Class> returnType, final Object[] args, final int[] defineParamIndexes, final Tuple2[] defineAnnos,
final BiFunction[] defineMappers, final boolean returnGeneratedKeys, final String[] returnColumnNames,
final List outParameterList, final Jdbc.BiParametersSetter parametersSetter) throws SQLException {
final OP op = queryInfo.op;
String query = queryInfo.sql;
ParsedSql parsedSql = queryInfo.parsedSql;
if (N.notEmpty(defineAnnos)) {
for (int i = 0, len = defineAnnos.length; i < len; i++) {
query = Strings.replaceAll(query, defineAnnos[i]._2, defineMappers[i].apply(defineAnnos[i]._1, args[defineParamIndexes[i]]));
}
if (N.notEmpty(parsedSql.getNamedParameters()) || parsedSql.getParameterCount() == 0) {
parsedSql = ParsedSql.parse(query);
query = parsedSql.sql();
}
}
AbstractQuery preparedQuery = null;
boolean noException = false;
try {
preparedQuery = queryInfo.isCall ? proxy.prepareCallableQuery(query)
: (queryInfo.isNamedQuery
? (returnGeneratedKeys ? proxy.prepareNamedQuery(parsedSql, returnColumnNames) : proxy.prepareNamedQuery(parsedSql))
: (returnGeneratedKeys ? proxy.prepareQuery(query, returnColumnNames) : proxy.prepareQuery(query)));
if (queryInfo.isCall && N.notEmpty(outParameterList)) {
final CallableQuery callableQuery = ((CallableQuery) preparedQuery);
for (final OutParameter outParameter : outParameterList) {
if (Strings.isEmpty(outParameter.name())) {
callableQuery.registerOutParameter(outParameter.position(), outParameter.sqlType());
} else {
callableQuery.registerOutParameter(outParameter.name(), outParameter.sqlType());
}
}
}
if (queryInfo.isSelect) {
preparedQuery.setFetchDirection(FetchDirection.FORWARD);
}
if (queryInfo.fetchSize > 0) {
preparedQuery.setFetchSize(queryInfo.fetchSize);
} else if (queryInfo.isSelect) {
if (mergedByIdAnno != null) {
preparedQuery.configStmt(JdbcUtil.stmtSetterForBigQueryResult); // ?
} else if (op == OP.findOnlyOne || op == OP.queryForUnique) {
preparedQuery.setFetchSize(2);
} else if (op == OP.findFirst || op == OP.queryForSingle || op == OP.exists || isExistsQuery(method, op, fullClassMethodName)
|| isSingleReturnType(returnType)) {
preparedQuery.setFetchSize(1);
} else if (op == OP.stream || op == OP.streamAll || Stream.class.isAssignableFrom(returnType)) {
preparedQuery.configStmt(JdbcUtil.stmtSetterForStream);
} else if (op == OP.list || op == OP.listAll || op == OP.query || op == OP.queryAll
|| isListQuery(method, returnType, op, fullClassMethodName)) {
preparedQuery.configStmt(JdbcUtil.stmtSetterForBigQueryResult);
} else if (op == OP.DEFAULT && (DataSet.class.isAssignableFrom(returnType))) {
preparedQuery.configStmt(JdbcUtil.stmtSetterForBigQueryResult);
}
}
if (queryInfo.queryTimeout >= 0) {
preparedQuery.setQueryTimeout(queryInfo.queryTimeout);
}
if (queryInfo.isBatch) {
if (queryInfo.isNamedQuery && queryInfo.timestamped && queryInfo.parsedSql.getNamedParameters().contains(PN_NOW)) {
preparedQuery.configAddBatchAction((q, s) -> {
((NamedQuery) q).setTimestamp(PN_NOW, Dates.currentTimestamp());
((PreparedStatement) s).addBatch();
});
}
} else {
preparedQuery.settParameters(args, parametersSetter);
}
noException = true;
} finally {
if (!noException && preparedQuery != null) {
preparedQuery.close();
}
}
return preparedQuery;
}
private static Condition handleLimit(final Condition cond, final int count, final DBVersion dbVersion) {
// if (count < 0) {
// return cond;
// }
if (cond instanceof final Limit limit) {
switch (dbVersion) { //NOSONAR
case ORACLE, SQL_SERVER, DB2:
if (limit.getCount() > 0 && limit.getOffset() > 0) {
return CF.limit("OFFSET " + limit.getOffset() + " ROWS FETCH NEXT " + limit.getCount() + " ROWS ONLY");
} else if (limit.getCount() > 0) {
return CF.limit("FETCH FIRST " + limit.getCount() + " ROWS ONLY");
} else if (limit.getOffset() > 0) {
return CF.limit("OFFSET " + limit.getOffset() + " ROWS");
} else {
return limit;
}
default:
return limit;
}
} else if (cond instanceof final Criteria criteria) {
final Limit limit = criteria.getLimit();
if (limit != null) {
switch (dbVersion) { //NOSONAR
case ORACLE, SQL_SERVER, DB2:
if (limit.getCount() > 0 && limit.getOffset() > 0) {
criteria.limit("OFFSET " + limit.getOffset() + " ROWS FETCH NEXT " + limit.getCount() + " ROWS ONLY");
} else if (limit.getCount() > 0) {
criteria.limit("FETCH FIRST " + limit.getCount() + " ROWS ONLY");
} else if (limit.getOffset() > 0) {
criteria.limit("OFFSET " + limit.getOffset() + " ROWS");
}
break;
default:
}
} else if (count > 0) {
switch (dbVersion) { //NOSONAR
case ORACLE, SQL_SERVER, DB2:
criteria.limit("FETCH FIRST " + count + " ROWS ONLY");
break;
default:
criteria.limit(count);
}
}
return criteria;
} else if (cond instanceof final Expression expr //
&& Strings.containsAnyIgnoreCase(expr.getLiteral(), " LIMIT ", " OFFSET ", " FETCH NEXT ")) {
// ignore.
} else if (count > 0) {
final Criteria criteria = CF.criteria();
if (cond != null) {
switch (cond.getOperator()) {
case LIMIT:
criteria.limit((Limit) cond);
break;
case ORDER_BY:
criteria.orderBy(cond);
break;
case GROUP_BY:
criteria.groupBy(cond);
break;
case UNION:
criteria.union((SubQuery) cond);
break;
case UNION_ALL:
criteria.unionAll((SubQuery) cond);
break;
case INTERSECT:
criteria.intersect((SubQuery) cond);
break;
case EXCEPT:
criteria.except((SubQuery) cond);
break;
case MINUS:
criteria.minus((SubQuery) cond);
break;
default:
criteria.where(cond);
}
}
switch (dbVersion) { //NOSONAR
case ORACLE, SQL_SERVER, DB2:
criteria.limit("FETCH FIRST " + count + " ROWS ONLY");
break;
default:
criteria.limit(count);
}
return criteria;
}
return cond;
}
@SuppressWarnings("unused")
private static String createCacheKey(final String fullClassMethodName, final Object[] args, final Logger daoLogger) {
String cachekey = null;
if (kryoParser != null) {
try {
cachekey = kryoParser.serialize(N.asMap(fullClassMethodName, args));
} catch (final Exception e) {
// ignore;
daoLogger.warn("Failed to generated cache key and not able cache the result for method: " + fullClassMethodName);
}
} else {
final List newArgs = Stream.of(args).map(it -> {
if (it == null) {
return "null";
}
final Type> type = N.typeOf(it.getClass());
if (type.isSerializable() || type.isCollection() || type.isMap() || type.isArray() || type.isBean() || type.isEntityId()) {
return it;
} else {
return it.toString();
}
}).toList();
try {
cachekey = N.toJson(N.asMap(fullClassMethodName, newArgs));
} catch (final Exception e) {
// ignore;
daoLogger.warn("Failed to generated cache key and not able cache the result for method: " + fullClassMethodName);
}
}
return cachekey;
}
@SuppressWarnings("rawtypes")
private static Jdbc.BiRowMapper getIdExtractor(final Holder> idExtractorHolder,
final Jdbc.BiRowMapper defaultIdExtractor, final Dao dao) {
Jdbc.BiRowMapper keyExtractor = idExtractorHolder.value();
if (keyExtractor == null) {
if (dao instanceof CrudDao) {
keyExtractor = N.defaultIfNull(((CrudDao) dao).idExtractor(), defaultIdExtractor);
} else {
keyExtractor = defaultIdExtractor;
}
idExtractorHolder.setValue(keyExtractor);
}
return keyExtractor;
}
private static void logDaoMethodPerf(final Logger daoLogger, final String simpleClassMethodName, final PerfLog perfLogAnno, final long startTime) {
if (JdbcUtil.isDaoMethodPerfLogAllowed && perfLogAnno.minExecutionTimeForOperation() >= 0 && daoLogger.isInfoEnabled()) {
final long elapsedTime = System.currentTimeMillis() - startTime;
if (elapsedTime >= perfLogAnno.minExecutionTimeForOperation()) {
daoLogger.info(Strings.concat("[DAO-OP-PERF]-[", simpleClassMethodName, "]: ", String.valueOf(elapsedTime)));
}
}
}
private static String getTableName(final Class> entityClass, final BeanInfo entityInfo, final NamingPolicy namingPolicy, final String targetTableName) {
if (Strings.isNotEmpty(targetTableName)) {
return targetTableName;
}
return entityInfo.tableName.orElseGet(() -> namingPolicy.convert(ClassUtil.getSimpleClassName(entityClass)));
}
private static T checkCondForPaginate(final T cond) {
N.checkArgNotNull(cond, "Condition for \"paginate\" can not be null");
if ((cond instanceof Criteria && ((Criteria) cond).getOrderBy() != null) || Strings.containsIgnoreCase(cond.toString(), " ORDER BY ")) {
// okay, has order by
} else {
throw new IllegalArgumentException("Condition for \"paginate\" must have \"orderBy\"");
}
return cond;
}
private static List batchGetById(final PreparedQuery preparedQuery, final Collection> ids, final Class entityClass)
throws DuplicatedResultException, SQLException {
final List entities = preparedQuery.settParameters(ids, collParamsSetter).list(entityClass);
if (entities.size() > ids.size()) {
throw new DuplicatedResultException("The size of result: " + entities.size() + " is bigger than the size of input ids: " + ids.size());
}
return entities;
}
@SuppressWarnings({ "rawtypes", "null", "resource" })
static TD createDao(final Class daoInterface, final String targetTableName, final javax.sql.DataSource ds, final SQLMapper sqlMapper,
final Cache daoCache, final Executor executor) {
N.checkArgNotNull(daoInterface, "daoInterface");
N.checkArgNotNull(ds, "dataSource");
N.checkArgument(daoInterface.isInterface(), "'daoInterface' must be an interface. It can't be {}", daoInterface);
final String daoCacheKey = ClassUtil.getCanonicalClassName(daoInterface) + "_" + targetTableName + "_" + System.identityHashCode(ds) + "_"
+ (sqlMapper == null ? "null" : System.identityHashCode(sqlMapper)) + "_" + (executor == null ? "null" : System.identityHashCode(executor));
TD daoInstance = (TD) daoPool.get(daoCacheKey);
if (daoInstance != null) {
return daoInstance;
}
final Logger daoLogger = LoggerFactory.getLogger(daoInterface);
final String daoClassName = ClassUtil.getCanonicalClassName(daoInterface);
final javax.sql.DataSource primaryDataSource = ds;
final DBProductInfo dbProductInfo = JdbcUtil.getDBProductInfo(ds);
final DBVersion dbVersion = dbProductInfo.getVersion();
final AsyncExecutor asyncExecutor = executor == null ? JdbcUtil.asyncExecutor : new AsyncExecutor(executor);
final boolean isUncheckedDao = UncheckedDao.class.isAssignableFrom(daoInterface);
final boolean isCrudDao = CrudDao.class.isAssignableFrom(daoInterface) || UncheckedCrudDao.class.isAssignableFrom(daoInterface);
final boolean isCrudDaoL = CrudDaoL.class.isAssignableFrom(daoInterface) || UncheckedCrudDaoL.class.isAssignableFrom(daoInterface);
final List> allInterfaces = StreamEx.of(ClassUtil.getAllInterfaces(daoInterface)).prepend(daoInterface).toList();
final SQLMapper newSQLMapper = sqlMapper == null ? new SQLMapper() : sqlMapper.copy();
StreamEx.of(allInterfaces) //
.flattMap(Class::getAnnotations)
.select(SqlMapper.class)
.map(SqlMapper::value)
.map(SQLMapper::fromFile)
.forEach(it -> {
for (final String key : it.keySet()) {
if (newSQLMapper.get(key) != null) {
throw new IllegalArgumentException("Duplicated sql keys: " + key + " defined in SQLMapper for Dao class: " + daoClassName);
}
newSQLMapper.add(key, it.get(key));
}
});
final boolean addLimitForSingleQuery = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(Config.class)
.map(Config::addLimitForSingleQuery)
.first()
.orElse(false);
final boolean callGenerateIdForInsert = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(Config.class)
.map(Config::callGenerateIdForInsertIfIdNotSet)
.first()
.orElse(false);
final boolean callGenerateIdForInsertWithSql = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(Config.class)
.map(Config::callGenerateIdForInsertWithSqlIfIdNotSet)
.first()
.orElse(false);
final boolean fetchColumnByEntityClassForDataSetQuery = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(Config.class)
.map(Config::fetchColumnByEntityClassForDataSetQuery)
.first()
.orElse(true);
final Map sqlFieldMap = StreamEx.of(allInterfaces)
.flattMap(Class::getDeclaredFields)
.append(StreamEx.of(allInterfaces).flattMap(Class::getDeclaredClasses).flattMap(Class::getDeclaredFields))
.filter(it -> it.isAnnotationPresent(SqlField.class))
.onEach(it -> N.checkArgument(Modifier.isStatic(it.getModifiers()) && Modifier.isFinal(it.getModifiers()) && String.class.equals(it.getType()),
"Field annotated with @SqlField must be static&final String. but {} is not in Dao class {}.", it, daoInterface))
.onEach(it -> ClassUtil.setAccessibleQuietly(it, true))
.map(it -> Tuple.of(it.getAnnotation(SqlField.class), it))
.map(it -> Tuple.of(Strings.isEmpty(it._1.id()) ? it._2.getName() : it._1.id(), it._2))
.onEach(it -> N.checkArgument(Strings.isNotEmpty(it._1) && !Strings.containsWhitespace(it._1),
"Sql id {} is empty or contains whitespace characters defined by field in Dao class {}.", it._1, daoInterface))
.distinctBy(it -> it._1, (a, b) -> {
throw new IllegalArgumentException(
"Two fields annotated with @SqlField have the same id (or name): " + a + "," + b + " in Dao class: " + daoClassName);
})
.toMap(it -> it._1, Fn.ff(it -> (String) (it._2.get(null))));
// Print out the embedded sqls because most of them may be generated by SQLBuilder.
if (daoLogger.isInfoEnabled() && N.notEmpty(sqlFieldMap)) {
daoLogger.info("Embedded sqls defined in declared classes for Dao interface: " + daoClassName);
sqlFieldMap.entrySet().forEach(it -> daoLogger.info(it.getKey() + " = " + it.getValue()));
}
if (!N.disjoint(newSQLMapper.keySet(), sqlFieldMap.keySet())) {
throw new IllegalArgumentException("Duplicated sql keys: " + N.commonSet(newSQLMapper.keySet(), sqlFieldMap.keySet())
+ " defined by both SQLMapper and SqlField for Dao interface: " + daoClassName);
}
for (final Map.Entry entry : sqlFieldMap.entrySet()) {
newSQLMapper.add(entry.getKey(), ParsedSql.parse(entry.getValue()));
}
final java.lang.reflect.Type[] typeArguments = Stream.of(allInterfaces)
.filter(it -> N.notEmpty(it.getGenericInterfaces()) && it.getGenericInterfaces()[0] instanceof ParameterizedType)
.map(it -> ((ParameterizedType) it.getGenericInterfaces()[0]).getActualTypeArguments())
.first()
.orElseNull();
if (N.notEmpty(typeArguments)) {
if ((typeArguments.length >= 1 && typeArguments[0] instanceof Class) && !ClassUtil.isBeanClass((Class) typeArguments[0])) {
throw new IllegalArgumentException(
"Entity Type parameter of Dao interface must be: Object.class or entity class with getter/setter methods. Can't be: "
+ typeArguments[0]);
}
if (JoinEntityHelper.class.isAssignableFrom(daoInterface) && (typeArguments.length >= 1 && typeArguments[0] instanceof Class)
&& ParserUtil.getBeanInfo((Class) typeArguments[0]).propInfoList.stream().noneMatch(it -> it.isSubEntity)) {
throw new IllegalArgumentException("Dao interface: " + ClassUtil.getCanonicalClassName(daoInterface)
+ " extends JoinEntityHelper, but the entity class: " + typeArguments[0] + " has no sub-entity properties.");
}
if (typeArguments.length >= 2 && SQLBuilder.class.isAssignableFrom((Class) typeArguments[1])) {
if (!(typeArguments[1].equals(PSC.class) || typeArguments[1].equals(PAC.class) || typeArguments[1].equals(PLC.class))) {
throw new IllegalArgumentException("SQLBuilder Type parameter must be: SQLBuilder.PSC/PAC/PLC. Can't be: " + typeArguments[1]);
}
} else if ((typeArguments.length >= 3 && SQLBuilder.class.isAssignableFrom((Class) typeArguments[2]))
&& !(typeArguments[2].equals(PSC.class) || typeArguments[2].equals(PAC.class) || typeArguments[2].equals(PLC.class))) {
throw new IllegalArgumentException("SQLBuilder Type parameter must be: SQLBuilder.PSC/PAC/PLC. Can't be: " + typeArguments[2]);
}
if (isCrudDao) {
final List idFieldNames = QueryUtil.getIdFieldNames((Class) typeArguments[0]);
if (idFieldNames.size() == 0) {
throw new IllegalArgumentException("To support CRUD operations by extending CrudDao interface, the entity class: " + typeArguments[0]
+ " must have at least one field annotated with @Id");
} else if (idFieldNames.size() == 1 && !SQLBuilder.class.isAssignableFrom((Class) typeArguments[1])) {
if (!(ClassUtil.wrap((Class) typeArguments[1]))
.isAssignableFrom(ClassUtil.wrap(ClassUtil.getPropGetMethod((Class) typeArguments[0], idFieldNames.get(0)).getReturnType()))) {
throw new IllegalArgumentException("The 'ID' type declared in Dao: " + ClassUtil.getCanonicalClassName(daoInterface)
+ " is not assignable from the id property type: "
+ ClassUtil.getPropGetMethod((Class) typeArguments[0], idFieldNames.get(0)).getReturnType());
}
} else if (idFieldNames.size() > 1 && !(EntityId.class.equals(typeArguments[1]) || ClassUtil.isBeanClass((Class) typeArguments[1])
|| ClassUtil.isRecordClass((Class) typeArguments[1]))) {
throw new IllegalArgumentException(
"To support composite ids, the 'ID' type must be EntityId/Entity/Record. It can't be: " + typeArguments[1]);
}
}
}
final Map> methodInvokerMap = new HashMap<>();
final List sqlMethods = StreamEx.of(allInterfaces)
.reversed()
.distinct()
.flattMap(Class::getDeclaredMethods)
.filter(m -> !Modifier.isStatic(m.getModifiers()))
.toList();
final Class extends SQLBuilder> sbc = N.isEmpty(typeArguments) ? PSC.class
: (typeArguments.length >= 2 && SQLBuilder.class.isAssignableFrom((Class) typeArguments[1]) ? (Class) typeArguments[1]
: (typeArguments.length >= 3 && SQLBuilder.class.isAssignableFrom((Class) typeArguments[2]) ? (Class) typeArguments[2] : PSC.class));
final NamingPolicy namingPolicy = sbc.equals(PSC.class) ? NamingPolicy.LOWER_CASE_WITH_UNDERSCORE
: (sbc.equals(PAC.class) ? NamingPolicy.UPPER_CASE_WITH_UNDERSCORE : NamingPolicy.LOWER_CAMEL_CASE);
final Class entityClass = N.isEmpty(typeArguments) ? null : (Class) typeArguments[0];
final BeanInfo entityInfo = entityClass == null ? null : ParserUtil.getBeanInfo(entityClass);
final String tableName = entityInfo == null ? null : getTableName(entityClass, entityInfo, namingPolicy, targetTableName);
final Class> idClass = isCrudDao ? (isCrudDaoL ? Long.class : (Class) typeArguments[1]) : null;
final boolean isEntityId = idClass != null && EntityId.class.isAssignableFrom(idClass);
final BeanInfo idBeanInfo = idClass != null && ClassUtil.isBeanClass(idClass) ? ParserUtil.getBeanInfo(idClass) : null;
final Function selectFromSQLBuilderFunc = sbc.equals(PSC.class)
? cond -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PSC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond).pair()
: PSC.select(entityClass).from(tableName).append(cond).pair()
: (sbc.equals(PAC.class)
? cond -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PAC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond).pair()
: PAC.select(entityClass).from(tableName).append(cond).pair()
: cond -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PLC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond).pair()
: PLC.select(entityClass).from(tableName).append(cond).pair());
final BiFunction singleQuerySQLBuilderFunc = sbc.equals(PSC.class)
? (selectPropName, cond) -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PSC.select(selectPropName).preselect(criteria.preselect()).from(tableName, entityClass).append(cond).pair()
: PSC.select(selectPropName).from(tableName, entityClass).append(cond).pair()
: (sbc.equals(PAC.class)
? (selectPropName, cond) -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PAC.select(selectPropName).preselect(criteria.preselect()).from(tableName, entityClass).append(cond).pair()
: PAC.select(selectPropName).from(tableName, entityClass).append(cond).pair()
: (selectPropName, cond) -> cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PLC.select(selectPropName).preselect(criteria.preselect()).from(tableName, entityClass).append(cond).pair()
: PLC.select(selectPropName).from(tableName, entityClass).append(cond).pair());
final BiFunction singleQueryByIdSQLBuilderFunc = sbc.equals(PSC.class)
? ((selectPropName, cond) -> NSC.select(selectPropName).from(tableName, entityClass).append(cond).pair())
: (sbc.equals(PAC.class) ? ((selectPropName, cond) -> NAC.select(selectPropName).from(tableName, entityClass).append(cond).pair())
: ((selectPropName, cond) -> NLC.select(selectPropName).from(tableName, entityClass).append(cond).pair()));
final BiFunction, Condition, SQLBuilder> selectSQLBuilderFunc = sbc.equals(PSC.class)
? ((selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PSC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: PSC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PSC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: PSC.select(selectPropNames).from(tableName, entityClass).append(cond))
: (sbc.equals(PAC.class)
? ((selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PAC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: PAC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PAC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: PAC.select(selectPropNames).from(tableName, entityClass).append(cond))
: (selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PLC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: PLC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? PLC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: PLC.select(selectPropNames).from(tableName, entityClass).append(cond));
final BiFunction, Condition, SQLBuilder> namedSelectSQLBuilderFunc = sbc.equals(PSC.class)
? ((selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NSC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: NSC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NSC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: NSC.select(selectPropNames).from(tableName, entityClass).append(cond))
: (sbc.equals(PAC.class)
? ((selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NAC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: NAC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NAC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: NAC.select(selectPropNames).from(tableName, entityClass).append(cond))
: (selectPropNames, cond) -> N.isEmpty(selectPropNames)
? (cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NLC.select(entityClass).preselect(criteria.preselect()).from(tableName).append(cond)
: NLC.select(entityClass).from(tableName).append(cond))
: cond instanceof final Criteria criteria && Strings.isNotEmpty(criteria.preselect())
? NLC.select(selectPropNames).preselect(criteria.preselect()).from(tableName, entityClass).append(cond)
: NLC.select(selectPropNames).from(tableName, entityClass).append(cond));
final Function, SQLBuilder> namedInsertSQLBuilderFunc = sbc.equals(PSC.class)
? (propNamesToInsert -> N.isEmpty(propNamesToInsert) ? NSC.insert(entityClass).into(tableName)
: NSC.insert(propNamesToInsert).into(tableName, entityClass))
: (sbc.equals(PAC.class)
? (propNamesToInsert -> N.isEmpty(propNamesToInsert) ? NAC.insert(entityClass).into(tableName)
: NAC.insert(propNamesToInsert).into(tableName, entityClass))
: (propNamesToInsert -> N.isEmpty(propNamesToInsert) ? NLC.insert(entityClass).into(tableName)
: NLC.insert(propNamesToInsert).into(tableName, entityClass)));
final BiFunction, SQLBuilder> parameterizedUpdateFunc = sbc.equals(PSC.class) ? PSC::update
: (sbc.equals(PAC.class) ? PAC::update : PLC::update);
final BiFunction, SQLBuilder> parameterizedDeleteFromFunc = sbc.equals(PSC.class) ? PSC::deleteFrom
: (sbc.equals(PAC.class) ? PAC::deleteFrom : PLC::deleteFrom);
final BiFunction, SQLBuilder> namedUpdateFunc = sbc.equals(PSC.class) ? NSC::update
: (sbc.equals(PAC.class) ? NAC::update : NLC::update);
final List idPropNameList = entityClass == null ? N.emptyList() : QueryUtil.getIdFieldNames(entityClass);
final boolean isNoId = entityClass == null || N.isEmpty(idPropNameList) || QueryUtil.isFakeId(idPropNameList);
final Set idPropNameSet = N.newHashSet(idPropNameList);
final String oneIdPropName = isNoId ? null : idPropNameList.get(0);
final PropInfo idPropInfo = isNoId ? null : entityInfo.getPropInfo(oneIdPropName);
final boolean isOneId = isNoId ? false : idPropNameList.size() == 1;
final Condition idCond = isNoId ? null : isOneId ? CF.eq(oneIdPropName) : CF.and(StreamEx.of(idPropNameList).map(CF::eq).toList());
final Function id2CondFunc = isNoId || idClass == null ? null
: (isEntityId ? id -> CF.id2Cond((EntityId) id)
: Map.class.isAssignableFrom(idClass) ? id -> CF.eqAnd((Map) id)
: ClassUtil.isBeanClass(idClass) || ClassUtil.isRecordClass(idClass) ? ConditionFactory::eqAnd
: id -> CF.eq(oneIdPropName, id));
N.checkArgument(
idPropNameList.size() > 1 || !(isEntityId || (idClass != null && (ClassUtil.isBeanClass(idClass) || Map.class.isAssignableFrom(idClass)))),
"Id type/class can not be EntityId/Map or Entity for single id ");
String sql_getById = null;
String sql_existsById = null;
String sql_insertWithId = null;
String sql_insertWithoutId = null;
String sql_updateById = null;
String sql_deleteById = null;
final boolean noOtherInsertPropNameExceptIdPropNames = idPropNameSet.containsAll(ClassUtil.getPropNameList(entityClass))
|| N.isEmpty(QueryUtil.getInsertPropNames(entityClass, idPropNameSet));
if (sbc.equals(PSC.class)) {
sql_getById = isNoId ? null : NSC.select(entityClass).from(tableName).where(idCond).sql();
sql_existsById = isNoId ? null : NSC.select(_1).from(tableName, entityClass).where(idCond).sql();
sql_insertWithId = entityClass == null ? null : NSC.insert(entityClass).into(tableName).sql();
sql_insertWithoutId = entityClass == null ? null
: (noOtherInsertPropNameExceptIdPropNames ? sql_insertWithId : NSC.insert(entityClass, idPropNameSet).into(tableName).sql());
sql_updateById = isNoId ? null : NSC.update(tableName).set(entityClass, idPropNameSet).where(idCond).sql();
sql_deleteById = isNoId ? null : NSC.deleteFrom(tableName, entityClass).where(idCond).sql();
} else if (sbc.equals(PAC.class)) {
sql_getById = isNoId ? null : NAC.select(entityClass).from(tableName).where(idCond).sql();
sql_existsById = isNoId ? null : NAC.select(_1).from(tableName, entityClass).where(idCond).sql();
sql_updateById = isNoId ? null : NAC.update(tableName).set(entityClass, idPropNameSet).where(idCond).sql();
sql_insertWithId = entityClass == null ? null : NAC.insert(entityClass).into(tableName).sql();
sql_insertWithoutId = entityClass == null ? null
: (noOtherInsertPropNameExceptIdPropNames ? sql_insertWithId : NAC.insert(entityClass, idPropNameSet).into(tableName).sql());
sql_deleteById = isNoId ? null : NAC.deleteFrom(tableName, entityClass).where(idCond).sql();
} else {
sql_getById = isNoId ? null : NLC.select(entityClass).from(tableName).where(idCond).sql();
sql_existsById = isNoId ? null : NLC.select(_1).from(tableName, entityClass).where(idCond).sql();
sql_insertWithId = entityClass == null ? null : NLC.insert(entityClass).into(tableName).sql();
sql_insertWithoutId = entityClass == null ? null
: (noOtherInsertPropNameExceptIdPropNames ? sql_insertWithId : NLC.insert(entityClass, idPropNameSet).into(tableName).sql());
sql_updateById = isNoId ? null : NLC.update(tableName).set(entityClass, idPropNameSet).where(idCond).sql();
sql_deleteById = isNoId ? null : NLC.deleteFrom(tableName, entityClass).where(idCond).sql();
}
final ParsedSql namedGetByIdSQL = Strings.isEmpty(sql_getById) ? null : ParsedSql.parse(sql_getById);
final ParsedSql namedExistsByIdSQL = Strings.isEmpty(sql_existsById) ? null : ParsedSql.parse(sql_existsById);
final ParsedSql namedInsertWithIdSQL = Strings.isEmpty(sql_insertWithId) ? null : ParsedSql.parse(sql_insertWithId);
final ParsedSql namedInsertWithoutIdSQL = Strings.isEmpty(sql_insertWithoutId) ? null : ParsedSql.parse(sql_insertWithoutId);
final ParsedSql namedUpdateByIdSQL = Strings.isEmpty(sql_updateById) ? null : ParsedSql.parse(sql_updateById);
final ParsedSql namedDeleteByIdSQL = Strings.isEmpty(sql_deleteById) ? null : ParsedSql.parse(sql_deleteById);
final ImmutableMap propColumnNameMap = QueryUtil.getProp2ColumnNameMap(entityClass, namingPolicy);
final String[] returnColumnNames = isNoId ? N.EMPTY_STRING_ARRAY
: (isOneId ? Array.of(propColumnNameMap.get(oneIdPropName))
: Stream.of(idPropNameList).map(propColumnNameMap::get).toArray(IntFunctions.ofStringArray()));
final Tuple3, Function, BiConsumer> tp3 = JdbcUtil.getIdGeneratorGetterSetter(daoInterface,
entityClass, namingPolicy, idClass);
final Holder> idExtractorHolder = new Holder<>();
final Jdbc.BiRowMapper idExtractor = tp3._1;
final Function idGetter = tp3._2;
final BiConsumer idSetter = tp3._3;
final Predicate isDefaultIdTester = isNoId ? id -> true
: (isOneId ? JdbcUtil::isDefaultIdPropValue
: (isEntityId ? id -> Stream.of(((EntityId) id).entrySet()).allMatch(it -> JdbcUtil.isDefaultIdPropValue(it.getValue()))
: id -> Stream.of(idPropNameList).allMatch(idName -> JdbcUtil.isDefaultIdPropValue(idBeanInfo.getPropValue(id, idName)))));
final Jdbc.BiParametersSetter idParamSetter = isOneId ? (pq, id) -> pq.setObject(oneIdPropName, id, idPropInfo.dbType)
: (isEntityId ? (pq, id) -> {
final EntityId entityId = (EntityId) id;
PropInfo propInfo = null;
for (final String idName : idPropNameList) {
propInfo = entityInfo.getPropInfo(idName);
pq.setObject(idName, entityId.get(idName), propInfo.dbType);
}
} : (pq, id) -> {
PropInfo propInfo = null;
for (final String idName : idPropNameList) {
propInfo = idBeanInfo.getPropInfo(idName);
pq.setObject(idName, propInfo.getPropValue(id), propInfo.dbType);
}
});
final Jdbc.BiParametersSetter idParamSetterByEntity = isOneId
? (pq, entity) -> pq.setObject(oneIdPropName, idPropInfo.getPropValue(entity), idPropInfo.dbType)
: (pq, entity) -> pq.settParameters(entity, objParamsSetter);
final CacheResult daoClassCacheResultAnno = StreamEx.of(allInterfaces).flattMap(Class::getAnnotations).select(CacheResult.class).first().orElseNull();
final RefreshCache daoClassRefreshCacheAnno = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(RefreshCache.class)
.first()
.orElseNull();
if (NoUpdateDao.class.isAssignableFrom(daoInterface) || UncheckedNoUpdateDao.class.isAssignableFrom(daoInterface)) {
// OK
} else {
// TODO maybe it's not a good idea to support Cache in general Dao which supports update/delete operations.
if (daoClassCacheResultAnno != null || daoClassRefreshCacheAnno != null) {
throw new UnsupportedOperationException(
"Cache is only supported for NoUpdateDao/UncheckedNoUpdateDao interface right now, not supported for Dao interface: " + daoClassName);
}
}
final MutableBoolean hasCacheResult = MutableBoolean.of(false);
final MutableBoolean hasRefreshCache = MutableBoolean.of(false);
final List daoClassHandlerList = StreamEx.of(allInterfaces)
.reversed()
.flattMap(Class::getAnnotations)
.filter(anno -> anno.annotationType().equals(Handler.class) || anno.annotationType().equals(HandlerList.class))
.flatmap(anno -> anno.annotationType().equals(Handler.class) ? N.asList((Handler) anno) : N.asList(((HandlerList) anno).value()))
.toList();
final Map> daoClassHandlerMap = StreamEx.of(allInterfaces)
.flattMap(Class::getDeclaredFields)
.append(StreamEx.of(allInterfaces).flattMap(Class::getDeclaredClasses).flattMap(Class::getDeclaredFields))
.filter(it -> Jdbc.Handler.class.isAssignableFrom(it.getType()))
.onEach(it -> N.checkArgument(Modifier.isStatic(it.getModifiers()) && Modifier.isFinal(it.getModifiers()),
"Handler Fields defined in Dao declared classes must be static&final Handler. but {} is not in Dao class {}.", it, daoInterface))
.onEach(it -> ClassUtil.setAccessibleQuietly(it, true))
.distinctBy(Field::getName, (a, b) -> {
throw new IllegalArgumentException("Two Handler fields have the same id (or name): " + a + "," + b + " in Dao class: " + daoClassName);
})
.toMap(Field::getName, Fn.ff(it -> (Jdbc.Handler>) it.get(null)));
final com.landawn.abacus.jdbc.annotation.Cache daoClassCacheAnno = StreamEx.of(allInterfaces)
.flattMap(Class::getAnnotations)
.select(com.landawn.abacus.jdbc.annotation.Cache.class)
.first()
.orElseNull();
final int capacity = daoClassCacheAnno == null ? DEFAULT_CACHE_CAPACITY : daoClassCacheAnno.capacity();
final long evictDelay = daoClassCacheAnno == null ? DEFAULT_EVICT_DELAY : daoClassCacheAnno.evictDelay();
if (NoUpdateDao.class.isAssignableFrom(daoInterface)) {
// OK
} else {
// TODO maybe it's not a good idea to support Cache in general Dao which supports update/delete operations.
if (daoCache != null || daoClassCacheAnno != null) {
throw new UnsupportedOperationException(
"Cache is only supported for NoUpdateDao/UncheckedNoUpdateDao interface right now, not supported for Dao interface: " + daoClassName);
}
}
final Cache cache = daoCache == null ? CacheFactory.createLocalCache(capacity, evictDelay) : daoCache;
final Set nonDBOperationSet = new HashSet<>();
// final Map sqlCache = new ConcurrentHashMap<>(0);
// final Map> sqlsCache = new ConcurrentHashMap<>(0);
final Map joinBeanInfo = JoinEntityHelper.class.isAssignableFrom(daoInterface)
? JoinInfo.getEntityJoinInfo(daoInterface, entityClass, tableName)
: null;
if (JoinEntityHelper.class.isAssignableFrom(daoInterface) && N.isEmpty(joinBeanInfo)) {
throw new IllegalArgumentException(
"Entity class: " + ClassUtil.getCanonicalClassName(entityClass) + " must have at least one join entity property for its Dao interface: "
+ ClassUtil.getCanonicalClassName(daoInterface) + " which extends JoinEntityHelper interface");
}
if ((JoinEntityHelper.class.isAssignableFrom(daoInterface) && !Dao.class.isAssignableFrom(daoInterface))
|| (CrudJoinEntityHelper.class.isAssignableFrom(daoInterface) && !CrudDao.class.isAssignableFrom(daoInterface))) {
throw new IllegalArgumentException("Dao interface: " + ClassUtil.getCanonicalClassName(entityClass)
+ " extending JoinEntityHelper/CrudJoinEntityHelper must extend the corresponding Dao interface:Dao/CrudDao");
}
final Predicate isNotEmptyResult = ret -> {
if (ret == null) {
return false;
}
if (ret instanceof DataSet) {
return N.notEmpty((DataSet) ret);
} else if (ret instanceof Collection) {
return N.notEmpty((Collection) ret);
} else if (ret instanceof Map) {
return N.notEmpty((Map) ret);
} else if (ret instanceof Iterable) {
return N.notEmpty((Iterable) ret);
} else if (ret instanceof Iterator) {
return N.notEmpty((Iterator) ret);
}
return true;
};
for (final Method method : sqlMethods) {
if (!Modifier.isPublic(method.getModifiers())) {
continue;
}
final boolean isNonDBOperation = StreamEx.of(method.getAnnotations()).anyMatch(anno -> anno.annotationType().equals(NonDBOperation.class));
final Predicate filterByMethodNameStartsWith = it -> Strings.isNotEmpty(it)
&& (Strings.startsWith(method.getName(), it) || Pattern.matches(it, method.getName()));
final Predicate filterByMethodNameContains = it -> Strings.isNotEmpty(it)
&& (Strings.containsIgnoreCase(method.getName(), it) || Pattern.matches(it, method.getName()));
final Class> declaringClass = method.getDeclaringClass();
final String methodName = method.getName();
final String simpleClassMethodName = declaringClass.getSimpleName() + "." + methodName;
final String fullClassMethodName = ClassUtil.getCanonicalClassName(declaringClass) + "." + methodName;
final Class>[] paramTypes = method.getParameterTypes();
final Class> returnType = method.getReturnType();
final int paramLen = paramTypes.length;
final boolean fetchColumnByEntityClass = StreamEx.of(method.getAnnotations())
.select(FetchColumnByEntityClass.class)
.map(FetchColumnByEntityClass::value)
.onEach(it -> N.checkArgument(DataSet.class.isAssignableFrom(returnType),
"@FetchColumnByEntityClass is not supported for method: {} because its return type is not DataSet", fullClassMethodName))
.first()
.orElse(fetchColumnByEntityClassForDataSetQuery);
final Sqls sqlsAnno = StreamEx.of(method.getAnnotations()).select(Sqls.class).onlyOne().orElseNull();
List sqlList = null;
if (sqlsAnno != null) {
if (Modifier.isAbstract(method.getModifiers())) {
throw new UnsupportedOperationException(
"Annotation @Sqls is only supported by interface methods with default implementation: default xxx dbOperationABC(someParameters, String ... sqls), not supported by abstract method: "
+ fullClassMethodName);
}
if (paramLen == 0 || !paramTypes[paramLen - 1].equals(String[].class)) {
throw new UnsupportedOperationException(
"To support sqls binding by @Sqls, the type of last parameter must be: String... sqls. It can't be : " + paramTypes[paramLen - 1]
+ " on method: " + fullClassMethodName);
}
if (newSQLMapper.isEmpty()) {
sqlList = Stream.of(sqlsAnno.value())
.map(Fn.strip())
.filter(Fn.notEmpty())
.map(sql -> sql.endsWith(";") ? sql.substring(0, sql.length() - 1) : sql)
.toList();
} else {
sqlList = Stream.of(sqlsAnno.value())
.map(Fn.strip())
.filter(Fn.notEmpty())
.map(it -> newSQLMapper.get(it) == null ? it : newSQLMapper.get(it).getParameterizedSql())
.map(sql -> sql.endsWith(";") ? sql.substring(0, sql.length() - 1) : sql)
.toList();
}
}
final String[] sqls = sqlList == null ? N.EMPTY_STRING_ARRAY : sqlList.toArray(new String[sqlList.size()]);
Throwables.BiFunction call = null;
if (!Modifier.isAbstract(method.getModifiers())) {
final MethodHandle methodHandle = createMethodHandle(method);
call = (proxy, args) -> {
if (sqlsAnno != null) {
if (N.notEmpty((String[]) args[paramLen - 1])) {
throw new IllegalArgumentException(
"The last parameter(String[]) of method annotated by @Sqls must be empty, don't specify it. It will be auto-filled by sqls from annotation @Sqls on the method: "
+ fullClassMethodName);
}
args[paramLen - 1] = sqls;
}
return methodHandle.bindTo(proxy).invokeWithArguments(args);
};
} else if (methodName.equals("executor") && Executor.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> asyncExecutor.getExecutor();
} else if (methodName.equals("asyncExecutor") && AsyncExecutor.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> asyncExecutor;
} else if (method.getName().equals("targetEntityClass") && Class.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> entityClass;
} else if (method.getName().equals("targetTableName") && String.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> tableName;
} else if (method.getName().equals("targetDaoInterface") && Class.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> daoInterface;
} else if (methodName.equals("dataSource") && javax.sql.DataSource.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> primaryDataSource;
} else if (methodName.equals("sqlMapper") && SQLMapper.class.isAssignableFrom(returnType) && paramLen == 0) {
call = (proxy, args) -> newSQLMapper;
// } else if (methodName.equals("cacheSql") && void.class.isAssignableFrom(returnType) && paramLen == 2 && paramTypes[0].equals(String.class)
// && paramTypes[1].equals(String.class)) {
// call = (proxy, args) -> {
// sqlCache.put(N.checkArgNotEmpty((String) args[0], "key"), N.checkArgNotEmpty((String) args[1], "sql"));
// return null;
// };
// } else if (methodName.equals("cacheSqls") && void.class.isAssignableFrom(returnType) && paramLen == 2 && paramTypes[0].equals(String.class)
// && paramTypes[1].equals(Collection.class)) {
// call = (proxy, args) -> {
// sqlsCache.put(N.checkArgNotEmpty((String) args[0], "key"),
// ImmutableList.copyOf(N.checkArgNotEmpty((Collection) args[1], "sqls")));
// return null;
// };
// } else if (methodName.equals("getCachedSql") && String.class.isAssignableFrom(returnType) && paramLen == 1 && paramTypes[0].equals(String.class)) {
// call = (proxy, args) -> sqlCache.get(args[0]);
// } else if (methodName.equals("getCachedSqls") && ImmutableList.class.isAssignableFrom(returnType) && paramLen == 1
// && paramTypes[0].equals(String.class)) {
// call = (proxy, args) -> sqlsCache.get(args[0]);
} else {
final boolean isStreamReturn = Stream.class.isAssignableFrom(returnType);
final boolean throwsSQLException = StreamEx.of(method.getExceptionTypes()).anyMatch(e -> e.isAssignableFrom(SQLException.class));
final Annotation sqlAnno = StreamEx.of(method.getAnnotations())
.filter(anno -> sqlAnnoMap.containsKey(anno.annotationType()))
.first()
.orElseNull();
if (declaringClass.equals(Dao.class) || declaringClass.equals(UncheckedDao.class)) {
if (methodName.equals("save") && paramLen == 1) {
call = (proxy, args) -> {
final Object entity = args[0];
N.checkArgNotNull(entity, "entity");
final ParsedSql namedInsertSQL = isNoId || isDefaultIdTester.test(idGetter.apply(entity)) ? namedInsertWithoutIdSQL
: namedInsertWithIdSQL;
proxy.prepareNamedQuery(namedInsertSQL).settParameters(entity, objParamsSetter).update();
return null;
};
} else if (methodName.equals("save") && paramLen == 2 && Collection.class.isAssignableFrom(paramTypes[1])) {
call = (proxy, args) -> {
final Object entity = args[0];
final Collection propNamesToSave = (Collection) args[1];
N.checkArgNotNull(entity, "entity");
N.checkArgNotEmpty(propNamesToSave, "propNamesToSave");
final String namedInsertSQL = namedInsertSQLBuilderFunc.apply(propNamesToSave).sql();
proxy.prepareNamedQuery(namedInsertSQL).settParameters(entity, objParamsSetter).update();
return null;
};
} else if (methodName.equals("save") && paramLen == 2 && String.class.equals(paramTypes[0])) {
call = (proxy, args) -> {
final String namedInsertSQL = (String) args[0];
final Object entity = args[1];
N.checkArgNotEmpty(namedInsertSQL, "namedInsertSQL");
N.checkArgNotNull(entity, "entity");
proxy.prepareNamedQuery(namedInsertSQL).settParameters(entity, objParamsSetter).update();
return null;
};
} else if (methodName.equals("batchSave") && paramLen == 2 && Collection.class.isAssignableFrom(paramTypes[0])
&& int.class.equals(paramTypes[1])) {
call = (proxy, args) -> {
final Collection> entities = (Collection) args[0];
final int batchSize = (Integer) args[1];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return 0;
}
final ParsedSql namedInsertSQL = isNoId || N.allMatch(entities, entity -> isDefaultIdTester.test(idGetter.apply(entity)))
? namedInsertWithoutIdSQL
: namedInsertWithIdSQL;
if (entities.size() <= batchSize) {
proxy.prepareNamedQuery(namedInsertSQL).addBatchParameters(entities).batchUpdate();
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL).closeAfterExecution(false)) {
Stream.of(entities)
.split(batchSize) //
.forEach(bp -> nameQuery.addBatchParameters(bp).batchUpdate());
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
return null;
};
} else if (methodName.equals("batchSave") && paramLen == 3 && Collection.class.isAssignableFrom(paramTypes[0])
&& Collection.class.isAssignableFrom(paramTypes[1]) && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final Collection> entities = (Collection) args[0];
final Collection propNamesToSave = (Collection) args[1];
N.checkArgNotEmpty(propNamesToSave, "propNamesToSave");
final int batchSize = (Integer) args[2];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return 0;
}
final String namedInsertSQL = namedInsertSQLBuilderFunc.apply(propNamesToSave).sql();
if (entities.size() <= batchSize) {
proxy.prepareNamedQuery(namedInsertSQL).addBatchParameters(entities).batchUpdate();
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL).closeAfterExecution(false)) {
Stream.of(entities)
.split(batchSize) //
.forEach(bp -> nameQuery.addBatchParameters(bp).batchUpdate());
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
return null;
};
} else if (methodName.equals("batchSave") && paramLen == 3 && String.class.equals(paramTypes[0])
&& Collection.class.isAssignableFrom(paramTypes[1]) && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final String namedInsertSQL = (String) args[0];
final Collection> entities = (Collection) args[1];
final int batchSize = (Integer) args[2];
N.checkArgNotEmpty(namedInsertSQL, "namedInsertSQL");
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return 0;
}
if (entities.size() <= batchSize) {
proxy.prepareNamedQuery(namedInsertSQL).addBatchParameters(entities).batchUpdate();
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL).closeAfterExecution(false)) {
Stream.of(entities)
.split(batchSize) //
.forEach(bp -> nameQuery.addBatchParameters(bp).batchUpdate());
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
return null;
};
} else if (methodName.equals("exists") && paramLen == 1 && Condition.class.isAssignableFrom(paramTypes[0])) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(_1, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).exists();
};
} else if (methodName.equals("count") && paramLen == 1 && Condition.class.isAssignableFrom(paramTypes[0])) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(SQLBuilder.COUNT_ALL, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForInt().orElseZero();
};
} else if (methodName.equals("findFirst") && paramLen == 1 && paramTypes[0].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(entityClass);
};
} else if (methodName.equals("findFirst") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(rowMapper);
};
} else if (methodName.equals("findFirst") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(rowMapper);
};
} else if (methodName.equals("findFirst") && paramLen == 2 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(entityClass);
};
} else if (methodName.equals("findFirst") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(rowMapper);
};
} else if (methodName.equals("findFirst") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(rowMapper);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 1 && paramTypes[0].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(entityClass);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 2 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(entityClass);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("findOnlyOne") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("queryForBoolean") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForBoolean();
};
} else if (methodName.equals("queryForChar") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForChar();
};
} else if (methodName.equals("queryForByte") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForByte();
};
} else if (methodName.equals("queryForShort") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForShort();
};
} else if (methodName.equals("queryForInt") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForInt();
};
} else if (methodName.equals("queryForLong") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForLong();
};
} else if (methodName.equals("queryForFloat") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForFloat();
};
} else if (methodName.equals("queryForDouble") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForDouble();
};
} else if (methodName.equals("queryForString") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForString();
};
} else if (methodName.equals("queryForDate") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForDate();
};
} else if (methodName.equals("queryForTime") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForTime();
};
} else if (methodName.equals("queryForTimestamp") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForTimestamp();
};
} else if (methodName.equals("queryForBytes") && paramLen == 2 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForBytes();
};
} else if (methodName.equals("queryForSingleResult") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Condition cond = (Condition) args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForSingleResult(targetType);
};
} else if (methodName.equals("queryForSingleNonNull") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Condition cond = (Condition) args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).queryForSingleNonNull(targetType);
};
} else if (methodName.equals("queryForSingleNonNull") && paramLen == 3 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper> rowMapper = (Jdbc.RowMapper>) args[2];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findFirst(rowMapper);
};
} else if (methodName.equals("queryForUniqueResult") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Condition cond = (Condition) args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).queryForUniqueResult(targetType);
};
} else if (methodName.equals("queryForUniqueNonNull") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Condition cond = (Condition) args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(2).settParameters(sp.parameters, collParamsSetter).queryForUniqueNonNull(targetType);
};
} else if (methodName.equals("queryForUniqueNonNull") && paramLen == 3 && paramTypes[0].equals(String.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper> rowMapper = (Jdbc.RowMapper>) args[2];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQuerySQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareQuery(sp.sql).setFetchSize(1).settParameters(sp.parameters, collParamsSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("query") && paramLen == 1 && paramTypes[0].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
if (fetchColumnByEntityClass) {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(Jdbc.ResultExtractor.toDataSet(entityClass));
} else {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query();
}
};
} else if (methodName.equals("query") && paramLen == 2 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[1];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply((Collection) args[0], limitedCond).pair();
if (fetchColumnByEntityClass) {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(Jdbc.ResultExtractor.toDataSet(entityClass));
} else {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query();
}
};
} else if (methodName.equals("query") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.ResultExtractor.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.ResultExtractor resultExtractor = (Jdbc.ResultExtractor) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(resultExtractor, "resultExtractor");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(resultExtractor);
};
} else if (methodName.equals("query") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.ResultExtractor.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.ResultExtractor resultExtractor = (Jdbc.ResultExtractor) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(resultExtractor, "resultExtractor");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(resultExtractor);
};
} else if (methodName.equals("query") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiResultExtractor.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiResultExtractor resultExtractor = (Jdbc.BiResultExtractor) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(resultExtractor, "resultExtractor");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(resultExtractor);
};
} else if (methodName.equals("query") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.BiResultExtractor.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiResultExtractor resultExtractor = (Jdbc.BiResultExtractor) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(resultExtractor, "resultExtractor");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.query(resultExtractor);
};
} else if (methodName.equals("paginate") && paramLen == 3 //
&& paramTypes[0].equals(Condition.class) //
&& paramTypes[1].equals(int.class) //
&& paramTypes[2].equals(Jdbc.BiParametersSetter.class)) {
call = (proxy, args) -> {
final Condition cond = checkCondForPaginate((Condition) args[0]);
final int pageSize = N.checkArgPositive((Integer) args[1], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[2],
"paramSetter");
final Jdbc.ResultExtractor resultExtractor = fetchColumnByEntityClass ? Jdbc.ResultExtractor.toDataSet(entityClass)
: Jdbc.ResultExtractor.TO_DATA_SET;
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return Stream.> just(Holder.of((DataSet) null)) //
.cycled()
.map(it -> {
try {
final DataSet ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(N::notEmpty);
};
} else if (methodName.equals("paginate") && paramLen == 4 //
&& paramTypes[0].equals(Condition.class) //
&& paramTypes[1].equals(int.class) //
&& paramTypes[2].equals(Jdbc.BiParametersSetter.class) //
&& paramTypes[3].equals(Jdbc.ResultExtractor.class)) {
call = (proxy, args) -> {
final Condition cond = checkCondForPaginate((Condition) args[0]);
final int pageSize = N.checkArgPositive((Integer) args[1], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[2],
"paramSetter");
final Jdbc.ResultExtractor resultExtractor = N.checkArgNotNull((Jdbc.ResultExtractor) args[3], "resultExtractor");
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return Stream.> just(Holder.of((Object) null)) //
.cycled()
.map(it -> {
try {
final Object ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(isNotEmptyResult);
};
} else if (methodName.equals("paginate") && paramLen == 4 //
&& paramTypes[0].equals(Condition.class) //
&& paramTypes[1].equals(int.class) //
&& paramTypes[2].equals(Jdbc.BiParametersSetter.class) //
&& paramTypes[3].equals(Jdbc.BiResultExtractor.class)) {
call = (proxy, args) -> {
final Condition cond = checkCondForPaginate((Condition) args[0]);
final int pageSize = N.checkArgPositive((Integer) args[1], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[2],
"paramSetter");
final Jdbc.BiResultExtractor resultExtractor = N.checkArgNotNull((Jdbc.BiResultExtractor) args[3], "resultExtractor");
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return Stream.> just(Holder.of((Object) null)) //
.cycled()
.map(it -> {
try {
final Object ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(isNotEmptyResult);
};
} else if (methodName.equals("paginate") && paramLen == 4 //
&& paramTypes[0].equals(Collection.class) //
&& paramTypes[1].equals(Condition.class) //
&& paramTypes[2].equals(int.class) //
&& paramTypes[3].equals(Jdbc.BiParametersSetter.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = checkCondForPaginate((Condition) args[1]);
final int pageSize = N.checkArgPositive((Integer) args[2], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[3],
"paramSetter");
final Jdbc.ResultExtractor resultExtractor = fetchColumnByEntityClass ? Jdbc.ResultExtractor.toDataSet(entityClass)
: Jdbc.ResultExtractor.TO_DATA_SET;
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return Stream.> just(Holder.of((DataSet) null)) //
.cycled()
.map(it -> {
try {
final DataSet ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(N::notEmpty);
};
} else if (methodName.equals("paginate") && paramLen == 5 //
&& paramTypes[0].equals(Collection.class) //
&& paramTypes[1].equals(Condition.class) //
&& paramTypes[2].equals(int.class) //
&& paramTypes[3].equals(Jdbc.BiParametersSetter.class) //
&& paramTypes[4].equals(Jdbc.ResultExtractor.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = checkCondForPaginate((Condition) args[1]);
final int pageSize = N.checkArgPositive((Integer) args[2], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[3],
"paramSetter");
final Jdbc.ResultExtractor resultExtractor = N.checkArgNotNull((Jdbc.ResultExtractor) args[4], "resultExtractor");
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return Stream.> just(Holder.of((Object) null)) //
.cycled()
.map(it -> {
try {
final Object ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(isNotEmptyResult);
};
} else if (methodName.equals("paginate") && paramLen == 5 //
&& paramTypes[0].equals(Collection.class) //
&& paramTypes[1].equals(Condition.class) //
&& paramTypes[2].equals(int.class) //
&& paramTypes[3].equals(Jdbc.BiParametersSetter.class) //
&& paramTypes[4].equals(Jdbc.BiResultExtractor.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = checkCondForPaginate((Condition) args[1]);
final int pageSize = N.checkArgPositive((Integer) args[2], "pageSize");
final Jdbc.BiParametersSetter paramSetter = N.checkArgNotNull((Jdbc.BiParametersSetter) args[3],
"paramSetter");
final Jdbc.BiResultExtractor resultExtractor = N.checkArgNotNull((Jdbc.BiResultExtractor) args[4], "resultExtractor");
final Condition limitedCond = handleLimit(cond, pageSize, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return Stream.> just(Holder.of((Object) null)) //
.cycled()
.map(it -> {
try {
final Object ret = proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.setFetchSize(pageSize)
.settParameters(sp.parameters, collParamsSetter)
.settParameters(it.value(), paramSetter)
.query(resultExtractor);
it.setValue(ret);
return ret;
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
})
.takeWhile(isNotEmptyResult);
};
} else if (methodName.equals("list") && paramLen == 1 && paramTypes[0].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(entityClass);
};
} else if (methodName.equals("list") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowMapper);
};
} else if (methodName.equals("list") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowMapper);
};
} else if (methodName.equals("list") && paramLen == 3 && paramTypes[0].equals(Condition.class) && paramTypes[1].equals(Jdbc.RowFilter.class)
&& paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowFilter, rowMapper);
};
} else if (methodName.equals("list") && paramLen == 3 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowFilter.class) && paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowFilter, rowMapper);
};
} else if (methodName.equals("list") && paramLen == 2 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(entityClass);
};
} else if (methodName.equals("list") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowMapper);
};
} else if (methodName.equals("list") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowMapper);
};
} else if (methodName.equals("list") && paramLen == 4 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.RowFilter.class) && paramTypes[3].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[2];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowFilter, rowMapper);
};
} else if (methodName.equals("list") && paramLen == 4 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.BiRowFilter.class) && paramTypes[3].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[2];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.list(rowFilter, rowMapper);
};
} else if (methodName.equals("stream") && paramLen == 1 && paramTypes[0].equals(Condition.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(entityClass);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 3 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowFilter.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowFilter, rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 3 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowFilter.class) && paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowFilter, rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 2 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotNull(cond, "cond");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(entityClass);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 3 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 4 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.RowFilter.class) && paramTypes[3].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[2];
final Jdbc.RowMapper rowMapper = (Jdbc.RowMapper) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowFilter, rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equals("stream") && paramLen == 4 && paramTypes[0].equals(Collection.class) && paramTypes[1].equals(Condition.class)
&& paramTypes[2].equals(Jdbc.BiRowFilter.class) && paramTypes[3].equals(Jdbc.BiRowMapper.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[2];
final Jdbc.BiRowMapper rowMapper = (Jdbc.BiRowMapper) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
final Supplier supplier = () -> {
try {
return proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForStream)
.settParameters(sp.parameters, collParamsSetter)
.stream(rowFilter, rowMapper);
} catch (final SQLException e) {
throw new UncheckedSQLException(e);
}
};
return Stream.of(supplier).flatMap(Supplier::get);
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowConsumer.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowConsumer rowConsumer = (Jdbc.RowConsumer) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 2 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowConsumer.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowConsumer rowConsumer = (Jdbc.BiRowConsumer) args[1];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 3 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.RowFilter.class) && paramTypes[2].equals(Jdbc.RowConsumer.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[1];
final Jdbc.RowConsumer rowConsumer = (Jdbc.RowConsumer) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowFilter, rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 3 && paramTypes[0].equals(Condition.class)
&& paramTypes[1].equals(Jdbc.BiRowFilter.class) && paramTypes[2].equals(Jdbc.BiRowConsumer.class)) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[1];
final Jdbc.BiRowConsumer rowConsumer = (Jdbc.BiRowConsumer) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectFromSQLBuilderFunc.apply(limitedCond);
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowFilter, rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowConsumer.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowConsumer rowConsumer = (Jdbc.RowConsumer) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 3 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.BiRowConsumer.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowConsumer rowConsumer = (Jdbc.BiRowConsumer) args[2];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 4 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowFilter.class)
&& paramTypes[3].equals(Jdbc.RowConsumer.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.RowFilter rowFilter = (Jdbc.RowFilter) args[2];
final Jdbc.RowConsumer rowConsumer = (Jdbc.RowConsumer) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowFilter, rowConsumer);
return null;
};
} else if (methodName.equalsIgnoreCase("forEach") && paramLen == 4 && paramTypes[0].equals(Collection.class)
&& paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.BiRowFilter.class)
&& paramTypes[3].equals(Jdbc.BiRowConsumer.class)) {
call = (proxy, args) -> {
final Collection selectPropNames = (Collection) args[0];
final Condition cond = (Condition) args[1];
final Jdbc.BiRowFilter rowFilter = (Jdbc.BiRowFilter) args[2];
final Jdbc.BiRowConsumer rowConsumer = (Jdbc.BiRowConsumer) args[3];
N.checkArgNotNull(cond, "cond");
N.checkArgNotNull(rowFilter, "rowFilter");
N.checkArgNotNull(rowConsumer, "rowConsumer");
final Condition limitedCond = handleLimit(cond, -1, dbVersion);
final SP sp = selectSQLBuilderFunc.apply(selectPropNames, limitedCond).pair();
proxy.prepareQuery(sp.sql)
.configStmt(JdbcUtil.stmtSetterForBigQueryResult)
.settParameters(sp.parameters, collParamsSetter)
.forEach(rowFilter, rowConsumer);
return null;
};
} else if (methodName.equals("update") && paramLen == 2 && Map.class.equals(paramTypes[0])
&& Condition.class.isAssignableFrom(paramTypes[1])) {
call = (proxy, args) -> {
final Map propsToUpdate = (Map) args[0];
final Condition cond = (Condition) args[1];
N.checkArgNotEmpty(propsToUpdate, "propsToUpdate");
N.checkArgNotNull(cond, "cond");
final SP sp = parameterizedUpdateFunc.apply(tableName, entityClass).set(propsToUpdate).append(cond).pair();
return proxy.prepareQuery(sp.sql).settParameters(sp.parameters, collParamsSetter).update();
};
} else if (methodName.equals("update") && paramLen == 3 && !Map.class.equals(paramTypes[0])
&& Collection.class.isAssignableFrom(paramTypes[1]) && Condition.class.isAssignableFrom(paramTypes[2])) {
call = (proxy, args) -> {
final Object entity = args[0];
final Collection propNamesToUpdate = (Collection) args[1];
final Condition cond = (Condition) args[2];
N.checkArgNotNull(entity, "entity");
N.checkArgNotEmpty(propNamesToUpdate, "propNamesToUpdate");
N.checkArgNotNull(cond, "cond");
final SP sp = parameterizedUpdateFunc.apply(tableName, entityClass).set(propNamesToUpdate).append(cond).pair();
final Jdbc.BiParametersSetter paramsSetter = (pq, p) -> {
final PreparedStatement stmt = pq.stmt;
PropInfo propInfo = null;
int columnIndex = 1;
for (final String propName : propNamesToUpdate) {
propInfo = entityInfo.getPropInfo(propName);
propInfo.dbType.set(stmt, columnIndex++, propInfo.getPropValue(p));
}
if (sp.parameters.size() > 0) {
for (final Object param : sp.parameters) {
pq.setObject(columnIndex++, param);
}
}
};
return proxy.prepareQuery(sp.sql).settParameters(entity, paramsSetter).update();
};
} else if (methodName.equals("delete") && paramLen == 1 && Condition.class.isAssignableFrom(paramTypes[0])) {
call = (proxy, args) -> {
final Condition cond = (Condition) args[0];
N.checkArgNotNull(cond, "cond");
final SP sp = parameterizedDeleteFromFunc.apply(tableName, entityClass).append(cond).pair();
return proxy.prepareQuery(sp.sql).settParameters(sp.parameters, collParamsSetter).update();
};
} else {
call = (proxy, args) -> {
throw new UnsupportedOperationException("Unsupported operation: " + method);
};
}
} else if (declaringClass.equals(CrudDao.class) || declaringClass.equals(UncheckedCrudDao.class)) {
if (methodName.equals("insert") && paramLen == 1) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final Object entity = args[0];
N.checkArgNotNull(entity, "entity");
ParsedSql namedInsertSQL = null;
if (isDefaultIdTester.test(idGetter.apply(entity))) {
if (callGenerateIdForInsert) {
idSetter.accept(((CrudDao) proxy).generateId(), entity);
namedInsertSQL = namedInsertWithIdSQL;
} else {
namedInsertSQL = namedInsertWithoutIdSQL;
}
} else {
namedInsertSQL = namedInsertWithIdSQL;
}
return proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.settParameters(entity, objParamsSetter)
.insert(keyExtractor, isDefaultIdTester)
.ifPresent(ret -> idSetter.accept(ret, entity))
.orElse(idGetter.apply(entity));
};
} else if (methodName.equals("insert") && paramLen == 2 && Collection.class.isAssignableFrom(paramTypes[1])) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final Object entity = args[0];
final Collection propNamesToInsert = (Collection) args[1];
N.checkArgNotNull(entity, "entity");
N.checkArgNotEmpty(propNamesToInsert, "propNamesToInsert");
if ((callGenerateIdForInsert && !N.disjoint(propNamesToInsert, idPropNameSet)) && isDefaultIdTester.test(idGetter.apply(entity))) {
idSetter.accept(((CrudDao) proxy).generateId(), entity);
}
final String namedInsertSQL = namedInsertSQLBuilderFunc.apply(propNamesToInsert).sql();
return proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.settParameters(entity, objParamsSetter)
.insert(keyExtractor, isDefaultIdTester)
.ifPresent(ret -> idSetter.accept(ret, entity))
.orElse(idGetter.apply(entity));
};
} else if (methodName.equals("insert") && paramLen == 2 && String.class.equals(paramTypes[0])) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final String namedInsertSQL = (String) args[0];
final Object entity = args[1];
N.checkArgNotEmpty(namedInsertSQL, "namedInsertSQL");
N.checkArgNotNull(entity, "entity");
if (callGenerateIdForInsertWithSql && isDefaultIdTester.test(idGetter.apply(entity))) {
idSetter.accept(((CrudDao) proxy).generateId(), entity);
}
return proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.settParameters(entity, objParamsSetter)
.insert(keyExtractor, isDefaultIdTester)
.ifPresent(ret -> idSetter.accept(ret, entity))
.orElse(idGetter.apply(entity));
};
} else if (methodName.equals("batchInsert") && paramLen == 2 && Collection.class.isAssignableFrom(paramTypes[0])
&& int.class.equals(paramTypes[1])) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final Collection> entities = (Collection) args[0];
final int batchSize = (Integer) args[1];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return new ArrayList<>();
}
final boolean allDefaultIdValue = N.allMatch(entities, entity -> isDefaultIdTester.test(idGetter.apply(entity)));
if (!allDefaultIdValue && callGenerateIdForInsert) {
final CrudDao crudDao = (CrudDao) proxy;
for (final Object entity : entities) {
if (isDefaultIdTester.test(idGetter.apply(entity))) {
idSetter.accept(crudDao.generateId(), entity);
}
}
}
final ParsedSql namedInsertSQL = allDefaultIdValue ? namedInsertWithoutIdSQL : namedInsertWithIdSQL;
List ids = null;
if (entities.size() <= batchSize) {
ids = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.addBatchParameters(entities)
.batchInsert(keyExtractor, isDefaultIdTester);
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames).closeAfterExecution(false)) {
ids = Seq.of(entities)
.split(batchSize)
.flatmap(bp -> nameQuery.addBatchParameters(bp).batchInsert(keyExtractor, isDefaultIdTester))
.toList();
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
if (JdbcUtil.isAllNullIds(ids)) {
ids = new ArrayList<>();
}
if ((N.notEmpty(ids) && N.size(ids) != N.size(entities)) && daoLogger.isWarnEnabled()) {
daoLogger.warn("The size of returned id list: {} is different from the size of input entity list: {}", ids.size(),
entities.size());
}
if (N.notEmpty(ids) && N.notEmpty(entities) && ids.size() == N.size(entities)) {
int idx = 0;
for (final Object e : entities) {
idSetter.accept(ids.get(idx++), e);
}
}
if (N.isEmpty(ids)) {
ids = Stream.of(entities).map(idGetter).toList();
}
return ids;
};
} else if (methodName.equals("batchInsert") && paramLen == 3 && Collection.class.isAssignableFrom(paramTypes[0])
&& Collection.class.isAssignableFrom(paramTypes[1]) && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final Collection> entities = (Collection) args[0];
final Collection propNamesToInsert = (Collection) args[1];
N.checkArgNotEmpty(propNamesToInsert, "propNamesToInsert");
final int batchSize = (Integer) args[1];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return new ArrayList<>();
}
if (callGenerateIdForInsert && !N.disjoint(propNamesToInsert, idPropNameSet)) {
final CrudDao crudDao = (CrudDao) proxy;
for (final Object entity : entities) {
if (isDefaultIdTester.test(idGetter.apply(entity))) {
idSetter.accept(crudDao.generateId(), entity);
}
}
}
final String namedInsertSQL = namedInsertSQLBuilderFunc.apply(propNamesToInsert).sql();
List ids = null;
if (entities.size() <= batchSize) {
ids = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.addBatchParameters(entities)
.batchInsert(keyExtractor, isDefaultIdTester);
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames).closeAfterExecution(false)) {
ids = Seq.of(entities)
.split(batchSize)
.flatmap(bp -> nameQuery.addBatchParameters(bp).batchInsert(keyExtractor, isDefaultIdTester))
.toList();
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
if (JdbcUtil.isAllNullIds(ids)) {
ids = new ArrayList<>();
}
if (N.notEmpty(ids) && N.notEmpty(entities) && ids.size() == N.size(entities)) {
int idx = 0;
for (final Object e : entities) {
idSetter.accept(ids.get(idx++), e);
}
}
if ((N.notEmpty(ids) && ids.size() != entities.size()) && daoLogger.isWarnEnabled()) {
daoLogger.warn("The size of returned id list: {} is different from the size of input entity list: {}", ids.size(),
entities.size());
}
if (N.isEmpty(ids)) {
ids = Stream.of(entities).map(idGetter).toList();
}
return ids;
};
} else if (methodName.equals("batchInsert") && paramLen == 3 && String.class.equals(paramTypes[0])
&& Collection.class.isAssignableFrom(paramTypes[1]) && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final Jdbc.BiRowMapper keyExtractor = getIdExtractor(idExtractorHolder, idExtractor, proxy);
final String namedInsertSQL = (String) args[0];
final Collection> entities = (Collection) args[1];
final int batchSize = (Integer) args[2];
N.checkArgNotEmpty(namedInsertSQL, "namedInsertSQL");
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return new ArrayList<>();
}
if (callGenerateIdForInsertWithSql) {
final CrudDao crudDao = (CrudDao) proxy;
for (final Object entity : entities) {
if (isDefaultIdTester.test(idGetter.apply(entity))) {
idSetter.accept(crudDao.generateId(), entity);
}
}
}
List ids = null;
if (entities.size() <= batchSize) {
ids = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames)
.addBatchParameters(entities)
.batchInsert(keyExtractor, isDefaultIdTester);
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedInsertSQL, returnColumnNames).closeAfterExecution(false)) {
ids = Seq.of(entities)
.split(batchSize)
.flatmap(bp -> nameQuery.addBatchParameters(bp).batchInsert(keyExtractor, isDefaultIdTester))
.toList();
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
if (JdbcUtil.isAllNullIds(ids)) {
ids = new ArrayList<>();
}
if ((N.notEmpty(ids) && N.size(ids) != N.size(entities)) && daoLogger.isWarnEnabled()) {
daoLogger.warn("The size of returned id list: {} is different from the size of input entity list: {}", ids.size(),
entities.size());
}
if (N.notEmpty(ids) && N.notEmpty(entities) && ids.size() == N.size(entities)) {
int idx = 0;
for (final Object e : entities) {
idSetter.accept(ids.get(idx++), e);
}
}
if (N.isEmpty(ids)) {
ids = Stream.of(entities).map(idGetter).toList();
}
return ids;
};
} else if (methodName.equals("queryForBoolean") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForBoolean();
};
} else if (methodName.equals("queryForChar") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForChar();
};
} else if (methodName.equals("queryForByte") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForByte();
};
} else if (methodName.equals("queryForShort") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForShort();
};
} else if (methodName.equals("queryForInt") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForInt();
};
} else if (methodName.equals("queryForLong") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForLong();
};
} else if (methodName.equals("queryForFloat") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForFloat();
};
} else if (methodName.equals("queryForDouble") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForDouble();
};
} else if (methodName.equals("queryForString") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForString();
};
} else if (methodName.equals("queryForDate") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForDate();
};
} else if (methodName.equals("queryForTime") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForTime();
};
} else if (methodName.equals("queryForTimestamp") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForTimestamp();
};
} else if (methodName.equals("queryForBytes") && paramLen == 2 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForBytes();
};
} else if (methodName.equals("queryForSingleResult") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && !paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Object id = args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForSingleResult(targetType);
};
} else if (methodName.equals("queryForSingleNonNull") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && !paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Object id = args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).queryForSingleNonNull(targetType);
};
} else if (methodName.equals("queryForSingleNonNull") && paramLen == 3 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
final Jdbc.RowMapper> rowMapper = (Jdbc.RowMapper>) args[2];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).findFirst(rowMapper);
};
} else if (methodName.equals("queryForUniqueResult") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && !paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Object id = args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(2).settParameters(id, idParamSetter).queryForUniqueResult(targetType);
};
} else if (methodName.equals("queryForUniqueNonNull") && paramLen == 3 && paramTypes[0].equals(Class.class)
&& paramTypes[1].equals(String.class) && !paramTypes[2].equals(Condition.class)) {
call = (proxy, args) -> {
final Class> targetType = (Class) args[0];
final String selectPropName = (String) args[1];
final Object id = args[2];
N.checkArgNotNull(targetType, "targetClass");
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 2 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(2).settParameters(id, idParamSetter).queryForUniqueNonNull(targetType);
};
} else if (methodName.equals("queryForUniqueNonNull") && paramLen == 3 && paramTypes[0].equals(String.class)
&& !paramTypes[1].equals(Condition.class) && paramTypes[2].equals(Jdbc.RowMapper.class)) {
call = (proxy, args) -> {
final String selectPropName = (String) args[0];
final Object id = args[1];
final Jdbc.RowMapper> rowMapper = (Jdbc.RowMapper>) args[2];
N.checkArgNotEmpty(selectPropName, "selectPropName");
N.checkArgNotNull(id, "id");
N.checkArgNotNull(rowMapper, "rowMapper");
final Condition limitedCond = handleLimit(idCond, addLimitForSingleQuery ? 1 : -1, dbVersion);
final SP sp = singleQueryByIdSQLBuilderFunc.apply(selectPropName, limitedCond);
return proxy.prepareNamedQuery(sp.sql).setFetchSize(1).settParameters(id, idParamSetter).findOnlyOne(rowMapper);
};
} else if (methodName.equals("gett")) {
if (paramLen == 1) {
call = (proxy, args) -> {
final Object id = args[0];
N.checkArgNotNull(id, "id");
return proxy.prepareNamedQuery(namedGetByIdSQL)
.setFetchSize(2)
.settParameters(id, idParamSetter)
.findOnlyOneOrNull(entityClass);
};
} else {
call = (proxy, args) -> {
final Object id = args[0];
N.checkArgNotNull(id, "id");
final Collection selectPropNames = (Collection) args[1];
if (N.isEmpty(selectPropNames)) {
return proxy.prepareNamedQuery(namedGetByIdSQL)
.setFetchSize(2)
.settParameters(id, idParamSetter)
.findOnlyOneOrNull(entityClass);
} else {
return proxy.prepareNamedQuery(namedSelectSQLBuilderFunc.apply(selectPropNames, idCond).sql())
.setFetchSize(2)
.settParameters(id, idParamSetter)
.findOnlyOneOrNull(entityClass);
}
};
}
} else if (methodName.equals("batchGet") && paramLen == 3 && Collection.class.equals(paramTypes[0])
&& Collection.class.equals(paramTypes[1]) && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final Collection ids = (Collection) args[0];
final Collection selectPropNames = (Collection) args[1];
final int batchSize = (Integer) args[2];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(ids)) {
return new ArrayList<>();
}
final Object firstId = N.firstElement(ids).get();
final boolean isMap = firstId instanceof Map;
final boolean isEntity = firstId != null && ClassUtil.isBeanClass(firstId.getClass());
N.checkArgument(idPropNameList.size() > 1 || !(isEntity || isMap || isEntityId),
"Input 'ids' can not be EntityIds/Maps or entities for single id ");
final List idList = ids instanceof List ? (List) ids : new ArrayList(ids);
final List resultList = new ArrayList<>(idList.size());
List entities = null;
if (idPropNameList.size() == 1) {
String sql_selectPart = selectSQLBuilderFunc.apply(selectPropNames, idCond).sql();
sql_selectPart = sql_selectPart.substring(0, sql_selectPart.lastIndexOf('=')) + "IN ";
if (idList.size() >= batchSize) {
final Joiner joiner = Joiner.with(", ", "(", ")").reuseCachedBuffer();
for (int i = 0; i < batchSize; i++) {
joiner.append('?');
}
final String qery = sql_selectPart + joiner.toString();
try (PreparedQuery preparedQuery = proxy.prepareQuery(qery)
.setFetchDirection(FetchDirection.FORWARD)
.setFetchSize(batchSize)
.closeAfterExecution(false)) {
for (int i = 0, to = idList.size() - batchSize; i <= to; i += batchSize) {
resultList.addAll(batchGetById(preparedQuery, idList.subList(i, i + batchSize), entityClass));
}
}
}
if (idList.size() % batchSize != 0) {
final int remaining = idList.size() % batchSize;
final Joiner joiner = Joiner.with(", ", "(", ")").reuseCachedBuffer();
for (int i = 0; i < remaining; i++) {
joiner.append('?');
}
final String qery = sql_selectPart + joiner.toString();
entities = batchGetById(proxy.prepareQuery(qery).setFetchDirection(FetchDirection.FORWARD).setFetchSize(remaining),
idList.subList(idList.size() - remaining, idList.size()), entityClass);
resultList.addAll(entities);
}
} else {
if (idList.size() >= batchSize) {
for (int i = 0, to = idList.size() - batchSize; i <= to; i += batchSize) {
if (isEntityId) {
entities = proxy.list(CF.id2Cond(idList.subList(i, i + batchSize)));
} else if (isMap) {
entities = proxy.list(CF.eqAndOr(idList.subList(i, i + batchSize)));
} else {
entities = proxy.list(CF.eqAndOr(idList.subList(i, i + batchSize), idPropNameList));
}
if (entities.size() > batchSize) {
throw new DuplicatedResultException(
"The size of result: " + entities.size() + " is bigger than the size of input ids: " + batchSize);
}
resultList.addAll(entities);
}
}
if (idList.size() % batchSize != 0) {
final int remaining = idList.size() % batchSize;
if (isEntityId) {
entities = proxy.list(CF.id2Cond(idList.subList(idList.size() - remaining, idList.size())));
} else if (isMap) {
entities = proxy.list(CF.eqAndOr(idList.subList(idList.size() - remaining, idList.size())));
} else {
entities = proxy.list(CF.eqAndOr(idList.subList(idList.size() - remaining, idList.size()), idPropNameList));
}
if (entities.size() > remaining) {
throw new DuplicatedResultException(
"The size of result: " + entities.size() + " is bigger than the size of input ids: " + remaining);
}
resultList.addAll(entities);
}
}
if (resultList.size() > idList.size()) {
throw new DuplicatedResultException(
"The size of result: " + resultList.size() + " is bigger than the size of input ids: " + idList.size());
}
return resultList;
};
} else if (methodName.equals("exists") && paramLen == 1 && !Condition.class.isAssignableFrom(paramTypes[0])) {
call = (proxy, args) -> {
final Object id = args[0];
N.checkArgNotNull(id, "id");
return proxy.prepareNamedQuery(namedExistsByIdSQL).setFetchSize(1).settParameters(id, idParamSetter).exists();
};
} else if (methodName.equals("count") && paramLen == 1 && Collection.class.equals(paramTypes[0])) {
final Collection selectPropNames = N.asList(SQLBuilder.COUNT_ALL);
final int batchSize = JdbcUtil.DEFAULT_BATCH_SIZE;
final String sql_selectPart = selectSQLBuilderFunc.apply(selectPropNames, idCond).sql();
final String sql_in_query = sql_selectPart.substring(0, sql_selectPart.lastIndexOf('=')) + "IN ";
call = (proxy, args) -> {
final Collection ids = (Collection) args[0];
if (N.isEmpty(ids)) {
return 0;
}
final Object firstId = N.firstElement(ids).get();
final boolean isMap = firstId instanceof Map;
final boolean isEntity = firstId != null && ClassUtil.isBeanClass(firstId.getClass());
N.checkArgument(idPropNameList.size() > 1 || !(isEntity || isMap || isEntityId),
"Input 'ids' can not be EntityIds/Maps or entities for single id ");
final List idList = ids instanceof Set ? new ArrayList(ids) : N.distinct(ids);
int result = 0;
if (idPropNameList.size() == 1) {
if (idList.size() >= batchSize) {
final Joiner joiner = Joiner.with(", ", "(", ")").reuseCachedBuffer();
for (int i = 0; i < batchSize; i++) {
joiner.append('?');
}
final String qery = sql_in_query + joiner.toString();
try (PreparedQuery preparedQuery = proxy.prepareQuery(qery)
.setFetchDirection(FetchDirection.FORWARD)
.closeAfterExecution(false)) {
for (int i = 0, to = idList.size() - batchSize; i <= to; i += batchSize) {
result += preparedQuery.settParameters(idList.subList(i, i + batchSize), collParamsSetter)
.queryForInt()
.orElseZero();
}
}
}
if (idList.size() % batchSize != 0) {
final int remaining = idList.size() % batchSize;
final Joiner joiner = Joiner.with(", ", "(", ")").reuseCachedBuffer();
for (int i = 0; i < remaining; i++) {
joiner.append('?');
}
final String qery = sql_in_query + joiner.toString();
result += proxy.prepareQuery(qery)
.setFetchDirection(FetchDirection.FORWARD)
.settParameters(idList.subList(idList.size() - remaining, idList.size()), collParamsSetter)
.queryForInt()
.orElseZero();
}
} else {
if (idList.size() >= batchSize) {
for (int i = 0, to = idList.size() - batchSize; i <= to; i += batchSize) {
if (isEntityId) {
result += proxy.count(CF.id2Cond(idList.subList(i, i + batchSize)));
} else if (isMap) {
result += proxy.count(CF.eqAndOr(idList.subList(i, i + batchSize)));
} else {
result += proxy.count(CF.eqAndOr(idList.subList(i, i + batchSize), idPropNameList));
}
}
}
if (idList.size() % batchSize != 0) {
final int remaining = idList.size() % batchSize;
if (isEntityId) {
result += proxy.count(CF.id2Cond(idList.subList(idList.size() - remaining, idList.size())));
} else if (isMap) {
result += proxy.count(CF.eqAndOr(idList.subList(idList.size() - remaining, idList.size())));
} else {
result += proxy.count(CF.eqAndOr(idList.subList(ids.size() - remaining, idList.size()), idPropNameList));
}
}
}
return result;
};
} else if (methodName.equals("update") && paramLen == 1) {
call = (proxy, args) -> {
final Object entity = args[0];
N.checkArgNotNull(entity, "entity");
return proxy.prepareNamedQuery(namedUpdateByIdSQL).settParameters(entity, objParamsSetter).update();
};
} else if (methodName.equals("update") && paramLen == 2 && !Map.class.equals(paramTypes[0]) && Collection.class.equals(paramTypes[1])) {
call = (proxy, args) -> {
final Object entity = args[0];
final Collection propNamesToUpdate = (Collection) args[1];
N.checkArgNotNull(entity, "entity");
N.checkArgNotEmpty(propNamesToUpdate, "propNamesToUpdate");
final String query = namedUpdateFunc.apply(tableName, entityClass).set(propNamesToUpdate).where(idCond).sql();
return proxy.prepareNamedQuery(query).settParameters(entity, objParamsSetter).update();
};
} else if (methodName.equals("update") && paramLen == 2 && Map.class.equals(paramTypes[0])) {
call = (proxy, args) -> {
final Map props = (Map) args[0];
final Object id = args[1];
N.checkArgNotEmpty(props, "propsToUpdate");
N.checkArgNotNull(id, "id");
// TODO not set by PropInfo.dbType of ids? it should be okay because Id should be simple type(int, long, String, UUID, Timestamp).
// If want to use idParamSetter, it has to be named sql. How to prepare/set named parameters? it's a problem to resolve.
final Condition cond = id2CondFunc.apply(id);
final SP sp = parameterizedUpdateFunc.apply(tableName, entityClass).set(props).append(cond).pair();
return proxy.prepareQuery(sp.sql).settParameters(sp.parameters, collParamsSetter).update();
};
} else if (methodName.equals("batchUpdate") && paramLen == 2 && int.class.equals(paramTypes[1])) {
call = (proxy, args) -> {
final Collection entities = (Collection) args[0];
final int batchSize = (Integer) args[1];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return 0;
}
long result = 0;
if (entities.size() <= batchSize) {
result = N.sum(proxy.prepareNamedQuery(namedUpdateByIdSQL).addBatchParameters(entities).batchUpdate());
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedUpdateByIdSQL).closeAfterExecution(false)) {
result = Seq.of(entities).split(batchSize).sumInt(bp -> N.sum(nameQuery.addBatchParameters(bp).batchUpdate()));
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
return Numbers.toIntExact(result);
};
} else if (methodName.equals("batchUpdate") && paramLen == 3 && int.class.equals(paramTypes[2])) {
call = (proxy, args) -> {
final Collection entities = (Collection) args[0];
final Collection propNamesToUpdate = (Collection) args[1];
final int batchSize = (Integer) args[2];
N.checkArgNotEmpty(propNamesToUpdate, "propNamesToUpdate");
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(entities)) {
return 0;
}
final String query = namedUpdateFunc.apply(tableName, entityClass).set(propNamesToUpdate).where(idCond).sql();
long result = 0;
if (entities.size() <= batchSize) {
result = N.sum(proxy.prepareNamedQuery(query).addBatchParameters(entities).batchUpdate());
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(query).closeAfterExecution(false)) {
result = Seq.of(entities).split(batchSize).sumInt(bp -> N.sum(nameQuery.addBatchParameters(bp).batchUpdate()));
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
}
return Numbers.toIntExact(result);
};
} else if (methodName.equals("deleteById")) {
call = (proxy, args) -> {
final Object id = args[0];
N.checkArgNotNull(id, "id");
return proxy.prepareNamedQuery(namedDeleteByIdSQL).settParameters(id, idParamSetter).update();
};
} else if (methodName.equals("delete") && paramLen == 1 && !Condition.class.isAssignableFrom(paramTypes[0])) {
call = (proxy, args) -> {
final Object entity = args[0];
N.checkArgNotNull(entity, "entity");
return proxy.prepareNamedQuery(namedDeleteByIdSQL).settParameters(entity, idParamSetterByEntity).update();
};
//} else if (methodName.equals("delete") && paramLen == 2 && !Condition.class.isAssignableFrom(paramTypes[0])
// && OnDeleteAction.class.equals(paramTypes[1])) {
// call = (proxy, args) -> {
// final Object entity = (args[0]);
// N.checkArgNotNull(entity, "entity");
// final OnDeleteAction onDeleteAction = (OnDeleteAction) args[1];
//
// if (onDeleteAction == null || onDeleteAction == OnDeleteAction.NO_ACTION) {
// return proxy.prepareNamedQuery(namedDeleteByIdSQL).settParameters(entity, idParamSetterByEntity).update();
// }
//
// final Map entityJoinInfo = JoinInfo.getEntityJoinInfo(entityClass);
//
// if (N.isEmpty(entityJoinInfo)) {
// return proxy.prepareNamedQuery(namedDeleteByIdSQL).settParameters(entity, idParamSetterByEntity).update();
// } else {
// final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
// long result = 0;
//
// try {
// Tuple2> tp = null;
//
// for (JoinInfo propJoinInfo : entityJoinInfo.values()) {
// tp = onDeleteAction == OnDeleteAction.SET_NULL ? propJoinInfo.getSetNullSqlAndParamSetter(sbc)
// : propJoinInfo.getDeleteSqlAndParamSetter(sbc);
//
// result += proxy.prepareQuery(tp._1).setParameters(entity, tp._2).update();
// }
//
// result += proxy.prepareNamedQuery(namedDeleteByIdSQL).settParameters(entity, idParamSetterByEntity).update();
//
// tran.commit();
// } finally {
// tran.rollbackIfNotCommitted();
// }
//
// return Numbers.toIntExact(result);
// }
// };
} else if ((methodName.equals("batchDelete") || methodName.equals("batchDeleteByIds")) && paramLen == 2
&& int.class.equals(paramTypes[1])) {
final Jdbc.BiParametersSetter paramSetter = methodName.equals("batchDeleteByIds") ? idParamSetter
: idParamSetterByEntity;
call = (proxy, args) -> {
final Collection idsOrEntities = (Collection) args[0];
final int batchSize = (Integer) args[1];
N.checkArgPositive(batchSize, "batchSize");
if (N.isEmpty(idsOrEntities)) {
return 0;
}
if (idsOrEntities.size() <= batchSize) {
return N.sum(proxy.prepareNamedQuery(namedDeleteByIdSQL).addBatchParameters(idsOrEntities, paramSetter).batchUpdate());
} else {
final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
long result = 0;
try {
try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedDeleteByIdSQL).closeAfterExecution(false)) {
result = Seq.of(idsOrEntities)
.split(batchSize)
.sumInt(bp -> N.sum(nameQuery.addBatchParameters(bp, paramSetter).batchUpdate()));
}
tran.commit();
} finally {
tran.rollbackIfNotCommitted();
}
return Numbers.toIntExact(result);
}
};
// } else if (methodName.equals("batchDelete") && paramLen == 3 && OnDeleteAction.class.equals(paramTypes[1])
// && int.class.equals(paramTypes[2])) {
// final JdbcUtil.BiParametersSetter paramSetter = idParamSetterByEntity;
//
// call = (proxy, args) -> {
// final Collection entities = (Collection) args[0];
// final OnDeleteAction onDeleteAction = (OnDeleteAction) args[1];
// final int batchSize = (Integer) args[2];
// N.checkArgPositive(batchSize, "batchSize");
//
// if (N.isEmpty(entities)) {
// return 0;
// } else if (onDeleteAction == null || onDeleteAction == OnDeleteAction.NO_ACTION) {
// return ((JdbcUtil.CrudDao) proxy).batchDelete(entities, batchSize);
// }
//
// final Map entityJoinInfo = JoinInfo.getEntityJoinInfo(entityClass);
//
// if (N.isEmpty(entityJoinInfo)) {
// return ((JdbcUtil.CrudDao) proxy).batchDelete(entities, batchSize);
// }
//
// final SQLTransaction tran = JdbcUtil.beginTransaction(proxy.dataSource());
// long result = 0;
//
// try {
// try (NamedQuery nameQuery = proxy.prepareNamedQuery(namedDeleteByIdSQL).closeAfterExecution(false)) {
// result = Stream.of(entities) //
// .splitToList(batchSize).checked() //
// .sumLong(bp -> {
// long tmpResult = 0;
//
// Tuple2> tp = null;
//
// for (JoinInfo propJoinInfo : entityJoinInfo.values()) {
// tp = onDeleteAction == OnDeleteAction.SET_NULL ? propJoinInfo.getSetNullSqlAndParamSetter(sbc)
// : propJoinInfo.getDeleteSqlAndParamSetter(sbc);
//
// tmpResult += N.sum(proxy.prepareQuery(tp._1).addBatchParameters2(bp, tp._2).batchUpdate());
// }
//
// tmpResult += N.sum(nameQuery.addBatchParameters(bp, paramSetter).batchUpdate());
//
// return tmpResult;
// })
// .orZero();
// }
//
// tran.commit();
// } finally {
// tran.rollbackIfNotCommitted();
// }
//
// return Numbers.toIntExact(result);
// };
} else {
call = (proxy, args) -> {
throw new UnsupportedOperationException("Unsupported operation: " + method);
};
}
} else if (declaringClass.equals(JoinEntityHelper.class) || declaringClass.equals(UncheckedJoinEntityHelper.class)) {
if (methodName.equals("loadJoinEntities") && paramLen == 3 && !Collection.class.isAssignableFrom(paramTypes[0])
&& String.class.isAssignableFrom(paramTypes[1]) && Collection.class.isAssignableFrom(paramTypes[2])) {
call = (proxy, args) -> {
final Object entity = args[0];
final String joinEntityPropName = (String) args[1];
final Collection selectPropNames = (Collection) args[2];
N.checkArgNotNull(entity, "entity");
N.checkArgNotEmpty(joinEntityPropName, "joinEntityPropName");
final JoinInfo propJoinInfo = joinBeanInfo.get(joinEntityPropName);
N.checkArgument(propJoinInfo != null, "No join entity property found by name: \"{}\" in class: {}", joinEntityPropName,
entityClass);
final Tuple2, String>, Jdbc.BiParametersSetter> tp = propJoinInfo
.getSelectSQLBuilderAndParamSetter(sbc);
final Dao, SQLBuilder, ?> joinEntityDao = getAppliableDaoForJoinEntity(propJoinInfo.referencedEntityClass, primaryDataSource,
proxy);
final PreparedQuery preparedQuery = joinEntityDao.prepareQuery(tp._1.apply(selectPropNames)).setParameters(entity, tp._2);
if (propJoinInfo.joinPropInfo.type.isCollection()) {
final List> propEntities = preparedQuery.list(propJoinInfo.referencedEntityClass);
if (propJoinInfo.joinPropInfo.clazz.isAssignableFrom(propEntities.getClass())) {
propJoinInfo.joinPropInfo.setPropValue(entity, propEntities);
} else {
final Collection c = N.newCollection((Class) propJoinInfo.joinPropInfo.clazz);
c.addAll(propEntities);
propJoinInfo.joinPropInfo.setPropValue(entity, c);
}
} else {
propJoinInfo.joinPropInfo.setPropValue(entity, preparedQuery.findFirst(propJoinInfo.referencedEntityClass).orElseNull());
}
return null;
};
} else if (methodName.equals("loadJoinEntities") && paramLen == 3 && Collection.class.isAssignableFrom(paramTypes[0])
&& String.class.isAssignableFrom(paramTypes[1]) && Collection.class.isAssignableFrom(paramTypes[2])) {
call = (proxy, args) -> {
final Collection entities = (Collection) args[0];
final String joinEntityPropName = (String) args[1];
final Collection selectPropNames = (Collection) args[2];
N.checkArgNotEmpty(joinEntityPropName, "joinEntityPropName");
final JoinInfo propJoinInfo = JoinInfo.getPropJoinInfo(daoInterface, entityClass, tableName, joinEntityPropName);
final Dao, SQLBuilder, ?> joinEntityDao = getAppliableDaoForJoinEntity(propJoinInfo.referencedEntityClass, primaryDataSource,
proxy);
if (N.isEmpty(entities)) {
// Do nothing.
} else if (entities.size() == 1) {
final Object first = N.firstOrNullIfEmpty(entities);
final Tuple2, String>, Jdbc.BiParametersSetter> tp = propJoinInfo
.getSelectSQLBuilderAndParamSetter(sbc);
final PreparedQuery preparedQuery = joinEntityDao.prepareQuery(tp._1.apply(selectPropNames)).setParameters(first, tp._2);
if (propJoinInfo.joinPropInfo.type.isCollection()) {
final List> propEntities = preparedQuery.list(propJoinInfo.referencedEntityClass);
if (propJoinInfo.joinPropInfo.clazz.isAssignableFrom(propEntities.getClass())) {
propJoinInfo.joinPropInfo.setPropValue(first, propEntities);
} else {
final Collection