Skip to content

Commit 2528720

Browse files
committed
Use ReentrantLock for compilation without synchronization
Closes gh-34133
1 parent 2bb4df7 commit 2528720

File tree

1 file changed

+28
-17
lines changed

1 file changed

+28
-17
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java

+28-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
24+
import java.util.concurrent.locks.Lock;
25+
import java.util.concurrent.locks.ReentrantLock;
2426

2527
import javax.sql.DataSource;
2628

@@ -66,6 +68,9 @@ public abstract class AbstractJdbcCall {
6668
/** List of RefCursor/ResultSet RowMapper objects. */
6769
private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<>();
6870

71+
/** Lock for the compilation step. */
72+
private final Lock compilationLock = new ReentrantLock();
73+
6974
/**
7075
* Has this operation been compiled? Compilation means at least checking
7176
* that a DataSource or JdbcTemplate has been provided.
@@ -284,24 +289,30 @@ public void addDeclaredRowMapper(String parameterName, RowMapper<?> rowMapper) {
284289
* @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't
285290
* been correctly initialized, for example if no DataSource has been provided
286291
*/
287-
public final synchronized void compile() throws InvalidDataAccessApiUsageException {
288-
if (!isCompiled()) {
289-
if (getProcedureName() == null) {
290-
throw new InvalidDataAccessApiUsageException("Procedure or Function name is required");
291-
}
292-
try {
293-
this.jdbcTemplate.afterPropertiesSet();
294-
}
295-
catch (IllegalArgumentException ex) {
296-
throw new InvalidDataAccessApiUsageException(ex.getMessage());
297-
}
298-
compileInternal();
299-
this.compiled = true;
300-
if (logger.isDebugEnabled()) {
301-
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") +
302-
" [" + getProcedureName() + "] compiled");
292+
public final void compile() throws InvalidDataAccessApiUsageException {
293+
this.compilationLock.lock();
294+
try {
295+
if (!isCompiled()) {
296+
if (getProcedureName() == null) {
297+
throw new InvalidDataAccessApiUsageException("Procedure or Function name is required");
298+
}
299+
try {
300+
this.jdbcTemplate.afterPropertiesSet();
301+
}
302+
catch (IllegalArgumentException ex) {
303+
throw new InvalidDataAccessApiUsageException(ex.getMessage());
304+
}
305+
compileInternal();
306+
this.compiled = true;
307+
if (logger.isDebugEnabled()) {
308+
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") +
309+
" [" + getProcedureName() + "] compiled");
310+
}
303311
}
304312
}
313+
finally {
314+
this.compilationLock.unlock();
315+
}
305316
}
306317

307318
/**

0 commit comments

Comments
 (0)