001/* 002 * Copyright 2015-2022 Transmogrify LLC, 2022-2025 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.pyranid; 018 019import javax.annotation.Nonnull; 020import java.sql.PreparedStatement; 021import java.sql.SQLException; 022import java.util.List; 023 024import static java.util.Objects.requireNonNull; 025 026/** 027 * Contract for binding parameters to SQL prepared statements. 028 * <p> 029 * A production-ready concrete implementation is available via the following static methods: 030 * <ul> 031 * <li>{@link #withDefaultConfiguration()}</li> 032 * <li>{@link #withCustomParameterBinders(List)}</li> 033 * </ul> 034 * How to acquire an instance: 035 * <pre>{@code // With out-of-the-box defaults 036 * PreparedStatementBinder default = PreparedStatementBinder.withDefaultConfiguration(); 037 * 038 * // Customized 039 * PreparedStatementBinder custom = PreparedStatementBinder.withCustomParameterBinders(List.of(...));}</pre> 040 * Or, implement your own: <pre>{@code PreparedStatementBinder myImpl = new PreparedStatementBinder() { 041 * @Override 042 * <T> void bindParameter( 043 * @Nonnull StatementContext<T> statementContext, 044 * @Nonnull PreparedStatement preparedStatement, 045 * @Nonnull Integer parameterIndex, 046 * @Nonnull Object parameter 047 * ) throws SQLException { 048 * // TODO: your own code that binds the parameter at the specified index to the PreparedStatement 049 * } 050 * };}</pre> 051 * 052 * @author <a href="https://www.revetkn.com">Mark Allen</a> 053 * @since 1.0.0 054 */ 055@FunctionalInterface 056public interface PreparedStatementBinder { 057 /** 058 * Binds a single parameter to a SQL prepared statement. 059 * <p> 060 * This function is only invoked when {@code parameter} is non-null. 061 * 062 * @param preparedStatement the prepared statement to bind to 063 * @param statementContext current SQL context 064 * @param parameterIndex the index of the parameter we are binding 065 * @param parameter the parameter we are binding to the {@link PreparedStatement}, if any 066 * @throws SQLException if an error occurs during binding 067 */ 068 <T> void bindParameter(@Nonnull StatementContext<T> statementContext, 069 @Nonnull PreparedStatement preparedStatement, 070 @Nonnull Integer parameterIndex, 071 @Nonnull Object parameter) throws SQLException; 072 073 /** 074 * Acquires a concrete implementation of this interface with out-of-the-box defaults. 075 * <p> 076 * The returned instance is thread-safe. 077 * 078 * @return a concrete implementation of this interface with out-of-the-box defaults 079 */ 080 @Nonnull 081 static PreparedStatementBinder withDefaultConfiguration() { 082 return new DefaultPreparedStatementBinder(); 083 } 084 085 /** 086 * Acquires a concrete implementation of this interface, specifying "surgical" per-type custom parameter binders. 087 * <p> 088 * The returned instance is thread-safe. 089 * 090 * @param customParameterBinders the "surgical" per-type custom parameter binders 091 * @return a concrete implementation of this interface 092 */ 093 @Nonnull 094 static PreparedStatementBinder withCustomParameterBinders(@Nonnull List<CustomParameterBinder> customParameterBinders) { 095 requireNonNull(customParameterBinders); 096 return new DefaultPreparedStatementBinder(customParameterBinders); 097 } 098}