• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

future-architect / uroborosql / #938

15 Dec 2025 03:16PM UTC coverage: 90.805%. Remained the same
#938

Pull #377

Copilot
Add clarifying comment for Iterable parameter logging

Co-authored-by: HidekiSugimoto189 <21981922+HidekiSugimoto189@users.noreply.github.com>
Pull Request #377: Change Parameter logging to TRACE level and optimize Iterable parameter logging

2 of 3 new or added lines in 1 file covered. (66.67%)

8 existing lines in 1 file now uncovered.

9224 of 10158 relevant lines covered (90.81%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.15
/src/main/java/jp/co/future/uroborosql/parameter/Parameter.java
1
/**
2
 * Copyright (c) 2017-present, Future Corporation
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
package jp.co.future.uroborosql.parameter;
8

9
import java.sql.JDBCType;
10
import java.sql.PreparedStatement;
11
import java.sql.SQLException;
12
import java.sql.SQLType;
13
import java.util.Map;
14
import java.util.Objects;
15

16
import jp.co.future.uroborosql.log.support.ServiceLoggingSupport;
17
import jp.co.future.uroborosql.log.support.SqlLoggingSupport;
18
import jp.co.future.uroborosql.parameter.mapper.BindParameterMapperManager;
19
import jp.co.future.uroborosql.utils.ObjectUtils;
20

21
/**
22
 * パラメータオブジェクト。<br>
23
 * SQLへバインドするパラメータを保持する。<br>
24
 *
25
 * @author H.Sugimoto
26
 */
27
public class Parameter implements ServiceLoggingSupport, SqlLoggingSupport {
28
        /** 未設定のSQLType */
29
        protected static final SQLType SQL_TYPE_NOT_SET = null;
1✔
30

31
        /**
32
         * パラメータ名
33
         */
34
        protected final String parameterName;
35

36
        /**
37
         * パラメータ値
38
         */
39
        protected final Object value;
40

41
        /**
42
         * SQL型
43
         */
44
        protected SQLType sqlType;
45

46
        /**
47
         * コンストラクタ。
48
         *
49
         * @param parameterName パラメータ名
50
         * @param value 値
51
         */
52
        public Parameter(final String parameterName, final Object value) {
53
                this(parameterName, value, SQL_TYPE_NOT_SET);
1✔
54
        }
1✔
55

56
        /**
57
         * コンストラクタ。
58
         *
59
         * @param parameterName パラメータ名
60
         * @param value 値
61
         * @param sqlType {@link java.sql.SQLType} で表される型
62
         */
63
        public Parameter(final String parameterName, final Object value, final SQLType sqlType) {
1✔
64
                this.parameterName = parameterName;
1✔
65
                this.value = value;
1✔
66
                this.sqlType = sqlType;
1✔
67
        }
1✔
68

69
        /**
70
         * コンストラクタ。
71
         *
72
         * @param parameterName パラメータ名
73
         * @param value 値
74
         * @param sqlType {@link java.sql.Types} で表される型
75
         */
76
        public Parameter(final String parameterName, final Object value, final int sqlType) {
1✔
77
                this.parameterName = parameterName;
1✔
78
                this.value = value;
1✔
79
                this.sqlType = toSqlType(sqlType);
1✔
80
        }
1✔
81

82
        /**
83
         * サブパラメータを生成する。 パラメータ値がBeanの場合、プロパティ名に対応するフィールド値をパラメータ値とする サブパラメータを作成して返す。
84
         *
85
         * @param propertyName プロパティ名
86
         * @return パラメータ
87
         */
88
        @SuppressWarnings("rawtypes")
89
        public Parameter createSubParameter(final String propertyName) {
90
                var subParameterName = parameterName + "." + propertyName;
1✔
91
                Object subValue = null;
1✔
92
                if (value != null) {
1✔
93
                        if (value instanceof Map) {
1✔
94
                                subValue = ((Map) value).get(propertyName);
×
95
                                if (subValue == null) {
×
96
                                        warnWith(LOG)
×
97
                                                        .setMessage("Set subparameter value to NULL because property can not be accessed.[{}]")
×
98
                                                        .addArgument(subParameterName)
×
99
                                                        .log();
×
100
                                }
101
                        } else {
102
                                try {
103
                                        // フィールドアクセスで値の取得を実施
104
                                        var field = value.getClass().getDeclaredField(propertyName);
1✔
105
                                        field.setAccessible(true);
1✔
106
                                        subValue = field.get(value);
1✔
107
                                } catch (NoSuchFieldException ex) {
1✔
108
                                        // メソッドアクセスで値の取得を実施
109
                                        try {
110
                                                var prefix = boolean.class.equals(value.getClass()) ? "is" : "get";
1✔
111
                                                var method = value.getClass()
1✔
112
                                                                .getMethod(prefix + ObjectUtils.capitalize(propertyName));
1✔
113
                                                subValue = method.invoke(value);
1✔
114
                                        } catch (Exception ex2) {
×
115
                                                warnWith(LOG)
×
116
                                                                .setMessage("Set subparameter value to NULL because property can not be accessed.[{}]")
×
117
                                                                .addArgument(subParameterName)
×
118
                                                                .setCause(ex2)
×
119
                                                                .log();
×
120
                                        }
1✔
121
                                } catch (Exception ex) {
×
122
                                        warnWith(LOG)
×
123
                                                        .setMessage("Set subparameter value to NULL because property can not be accessed.[{}]")
×
124
                                                        .addArgument(subParameterName)
×
125
                                                        .setCause(ex)
×
126
                                                        .log();
×
127
                                }
1✔
128
                        }
129
                }
130

131
                return new Parameter(subParameterName, subValue);
1✔
132

133
        }
134

135
        /**
136
         * ステートメントへパラメータ値をバインド。
137
         *
138
         * @param preparedStatement ステートメント
139
         * @param index パラメータインデックス
140
         * @param parameterMapperManager パラメータ変換管理クラス
141
         * @return 次のパラメータインデックス
142
         * @throws SQLException SQL例外
143
         */
144
        public int setParameter(final PreparedStatement preparedStatement, final int index,
145
                        final BindParameterMapperManager parameterMapperManager) throws SQLException {
146
                return setInParameter(preparedStatement, index, parameterMapperManager);
1✔
147
        }
148

149
        /**
150
         * ステートメントへ入力パラメータ値をバインド。
151
         *
152
         * @param preparedStatement ステートメント
153
         * @param index パラメータインデックス
154
         * @param parameterMapperManager パラメータ変換管理クラス
155
         * @return 次のパラメータインデックス
156
         * @throws SQLException SQL例外
157
         */
158
        protected int setInParameter(final PreparedStatement preparedStatement, final int index,
159
                        final BindParameterMapperManager parameterMapperManager) throws SQLException {
160
                var parameterIndex = index;
1✔
161
                if (value instanceof Iterable) {
1✔
162
                        for (var e : (Iterable<?>) value) {
1✔
163
                                setParameterObject(preparedStatement, parameterIndex, e, parameterMapperManager);
1✔
164
                                parameterIndex++;
1✔
165
                        }
1✔
166
                        // Log once for the entire Iterable parameter using the starting index
167
                        parameterLog(index);
1✔
168
                } else {
169
                        setParameterObject(preparedStatement, parameterIndex, value, parameterMapperManager);
1✔
170
                        parameterLog(parameterIndex);
1✔
171
                        parameterIndex++;
1✔
172
                }
173

174
                return parameterIndex;
1✔
175
        }
176

177
        /**
178
         * パラメータ設定ログ出力。
179
         *
180
         * @param index パラメータインデックス
181
         */
182
        protected void parameterLog(final int index) {
183
                if (SQL_LOG.isTraceEnabled() && !isSuppressParameterLogging()) {
1✔
NEW
184
                        traceWith(SQL_LOG)
×
185
                                        .setMessage("Set the parameter.[INDEX[{}], {}]")
×
186
                                        .addArgument(index)
×
UNCOV
187
                                        .addArgument(this)
×
UNCOV
188
                                        .log();
×
189
                }
190
        }
1✔
191

192
        /**
193
         * パラメータ名取得。
194
         *
195
         * @return パラメータ名
196
         */
197
        public String getParameterName() {
198
                return parameterName;
1✔
199
        }
200

201
        /**
202
         * パラメータ値取得。
203
         *
204
         * @return パラメータ値
205
         */
206
        public Object getValue() {
207
                return value;
1✔
208
        }
209

210
        /**
211
         * SQLType取得。
212
         *
213
         * @return SQLType
214
         */
215
        public SQLType getSqlType() {
216
                return sqlType;
1✔
217
        }
218

219
        /**
220
         * SQLType設定。
221
         *
222
         * @param sqlType SQLType
223
         */
224
        public void setSqlType(final SQLType sqlType) {
UNCOV
225
                this.sqlType = sqlType;
×
UNCOV
226
        }
×
227

228
        /**
229
         * {@inheritDoc}
230
         *
231
         * @see java.lang.Object#toString()
232
         */
233
        @Override
234
        public String toString() {
235
                return "Parameter name[" + parameterName + "], Value[" + value + "], Class["
1✔
236
                                + (value == null ? "NULL" : value.getClass().getSimpleName())
1✔
237
                                + (Objects.equals(sqlType, SQL_TYPE_NOT_SET) ? "]" : "], SQL type[" + sqlType.getName() + "]");
1✔
238
        }
239

240
        /**
241
         * {@link java.sql.Types} の値を {@link java.sql.SQLType} に変換する
242
         * @param sqlType {@link java.sql.Types} の値
243
         * @return {@link java.sql.SQLType} の値
244
         */
245
        private SQLType toSqlType(final int sqlType) {
246
                for (var type : JDBCType.values()) {
1✔
247
                        if (type.getVendorTypeNumber().intValue() == sqlType) {
1✔
248
                                return type;
1✔
249
                        }
250
                }
251
                //下位互換のため、念のため生成して返す
UNCOV
252
                return new SQLType() {
×
253
                        @Override
254
                        public Integer getVendorTypeNumber() {
UNCOV
255
                                return sqlType;
×
256
                        }
257

258
                        @Override
259
                        public String getVendor() {
UNCOV
260
                                return "unknown";
×
261
                        }
262

263
                        @Override
264
                        public String getName() {
UNCOV
265
                                return "unknown name:" + sqlType;
×
266
                        }
267
                };
268
        }
269

270
        /**
271
         * PreparedStatementへのパラメータセット処理
272
         *
273
         * @param preparedStatement PreparedStatement
274
         * @param parameterIndex index
275
         * @param param オリジナルパラメータ
276
         * @param parameterMapperManager パラメータ変換管理クラス
277
         * @throws SQLException SQL例外
278
         */
279
        private void setParameterObject(final PreparedStatement preparedStatement, final int parameterIndex,
280
                        final Object param, final BindParameterMapperManager parameterMapperManager) throws SQLException {
281
                //JDBCの受け付ける型に変換
282
                var jdbcParam = parameterMapperManager.toJdbc(param, preparedStatement.getConnection());
1✔
283
                if (Objects.equals(sqlType, SQL_TYPE_NOT_SET)) {
1✔
284
                        if (jdbcParam instanceof java.sql.Array) {
1✔
285
                                preparedStatement.setArray(parameterIndex, (java.sql.Array) jdbcParam);
1✔
286
                        } else {
287
                                if (jdbcParam != null) {
1✔
288
                                        preparedStatement.setObject(parameterIndex, jdbcParam);
1✔
289
                                } else {
290
                                        preparedStatement.setNull(parameterIndex, JDBCType.NULL.getVendorTypeNumber());
1✔
291
                                }
292
                        }
293
                } else {
294
                        int targetSqlType = sqlType.getVendorTypeNumber();//各JDBCの対応状況が怪しいのでintで扱う
1✔
295
                        if (jdbcParam != null) {
1✔
296
                                if (jdbcParam instanceof java.sql.Array) {
1✔
297
                                        preparedStatement.setArray(parameterIndex, (java.sql.Array) jdbcParam);
1✔
298
                                } else {
299
                                        preparedStatement.setObject(parameterIndex, jdbcParam, targetSqlType);
1✔
300
                                }
301
                        } else {
302
                                preparedStatement.setNull(parameterIndex, targetSqlType);
1✔
303
                        }
304
                }
305
        }
1✔
306
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc