Browse Source

Use ReentrantLock for compilation without synchronization

Closes gh-34133
pull/34398/head
Juergen Hoeller 11 months ago
parent
commit
25287205ba
  1. 45
      spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,6 +21,8 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -66,6 +68,9 @@ public abstract class AbstractJdbcCall {
/** List of RefCursor/ResultSet RowMapper objects. */ /** List of RefCursor/ResultSet RowMapper objects. */
private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<>(); private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<>();
/** Lock for the compilation step. */
private final Lock compilationLock = new ReentrantLock();
/** /**
* Has this operation been compiled? Compilation means at least checking * Has this operation been compiled? Compilation means at least checking
* that a DataSource or JdbcTemplate has been provided. * that a DataSource or JdbcTemplate has been provided.
@ -284,24 +289,30 @@ public abstract class AbstractJdbcCall {
* @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't * @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't
* been correctly initialized, for example if no DataSource has been provided * been correctly initialized, for example if no DataSource has been provided
*/ */
public final synchronized void compile() throws InvalidDataAccessApiUsageException { public final void compile() throws InvalidDataAccessApiUsageException {
if (!isCompiled()) { this.compilationLock.lock();
if (getProcedureName() == null) { try {
throw new InvalidDataAccessApiUsageException("Procedure or Function name is required"); if (!isCompiled()) {
} if (getProcedureName() == null) {
try { throw new InvalidDataAccessApiUsageException("Procedure or Function name is required");
this.jdbcTemplate.afterPropertiesSet(); }
} try {
catch (IllegalArgumentException ex) { this.jdbcTemplate.afterPropertiesSet();
throw new InvalidDataAccessApiUsageException(ex.getMessage()); }
} catch (IllegalArgumentException ex) {
compileInternal(); throw new InvalidDataAccessApiUsageException(ex.getMessage());
this.compiled = true; }
if (logger.isDebugEnabled()) { compileInternal();
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") + this.compiled = true;
" [" + getProcedureName() + "] compiled"); if (logger.isDebugEnabled()) {
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") +
" [" + getProcedureName() + "] compiled");
}
} }
} }
finally {
this.compilationLock.unlock();
}
} }
/** /**

Loading…
Cancel
Save