AutoFunctionCallImpl.java
package com.github.mygreen.sqlmapper.core.query.auto;
import java.util.Map;
import java.util.Optional;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import com.github.mygreen.sqlmapper.core.SqlMapperContext;
import com.github.mygreen.sqlmapper.core.StoredName;
import com.github.mygreen.sqlmapper.core.meta.StoredParamMeta;
import com.github.mygreen.sqlmapper.core.query.JdbcTemplateBuilder;
import lombok.Getter;
/**
* ストアドファンクションを呼び出すためのSQLを自動生成する処理の実装です。
* <p>戻り値がRETURN文の場合のみ対応し、OUTパラメータ、RESULT_SETの場合は、{@link AutoProcedureCallImpl}を使用します。
*
* @author T.TSUCHIE
*
* @param <T> ストアドファンクションの戻り値のタイプ
*/
public class AutoFunctionCallImpl<T> extends AutoStoredExecutorSupport implements AutoFunctionCall<T> {
/**
* 戻り値のクラス
*/
private final Class<T> resultClass;
/**
* 呼び出すストアドファンクション名
*/
@Getter
private final StoredName functionName;
/**
* パラメータ
*/
@Getter
private final Optional<Object> parameter;
/**
* パラメータのメタ情報。
* パラメータが空の時は{@literal null}を設定。
*/
private final StoredParamMeta paramMeta;
@Getter
private Integer queryTimeout;
public AutoFunctionCallImpl(SqlMapperContext context, final Class<T> resultClass, final StoredName functionName) {
super(context);
this.resultClass = resultClass;
this.functionName = functionName;
this.parameter = Optional.empty();
this.paramMeta = null;
}
public AutoFunctionCallImpl(SqlMapperContext context, final Class<T> resultClass, final StoredName functionName, final Object parameter) {
super(context);
this.resultClass = resultClass;
this.functionName = functionName;
this.parameter = Optional.of(parameter);
this.paramMeta = context.getStoredParamMetaFactory().create(parameter.getClass());
}
@Override
public AutoFunctionCallImpl<T> queryTimeout(int seconds) {
this.queryTimeout = seconds;
return this;
}
@Override
public T execute() {
final SimpleJdbcCall jdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName(functionName.getName());
if(functionName.getCatalog() != null) {
jdbcCall.withCatalogName(functionName.getCatalog());
}
if(functionName.getSchema() != null) {
jdbcCall.withSchemaName(functionName.getSchema());
}
if(parameter.isEmpty()) {
return jdbcCall.executeFunction(resultClass);
} else {
SqlParameter[] parameterTypes = createSqlParameterTypes(paramMeta);
Object[] parameterValues = parameter.map(p -> createParameterValues(paramMeta, p))
.orElseGet(() -> new Object[0]);
if(containsResultParam(paramMeta, parameter)) {
Map<String, Object> out = jdbcCall.declareParameters(parameterTypes)
.execute(parameterValues);
// 戻り値を持つパラメータの処理を行う。
doResultValue(paramMeta, parameter.get(), out);
return null;
} else {
// SimpleJdbcCallは、OUTパラメータと戻り値(ResultSet)は併用できない。
return jdbcCall.declareParameters(parameterTypes)
.executeFunction(resultClass, parameterValues);
}
}
}
/**
* {@link JdbcTemplate}を取得します。
* @return {@link JdbcTemplate}のインスタンス。
*/
private JdbcTemplate getJdbcTemplate() {
return JdbcTemplateBuilder.create(context.getDataSource(), context.getJdbcTemplateProperties())
.queryTimeout(queryTimeout)
.build();
}
}