This is an automated email from the ASF dual-hosted git repository. garydgregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-dbutils.git
commit 39d62c2e661ac753e09db90ff8707173f0dc79e1 Author: Gary Gregory <[email protected]> AuthorDate: Sat Aug 22 08:58:51 2026 -0400 Bump org.apache.commons:commons-parent from 103 to 104. --- pom.xml | 2 +- src/changes/changes.xml | 3 ++- .../org/apache/commons/dbutils/QueryLoader.java | 26 +++++++++++++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index cee705f..c849a5a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.apache.commons</groupId> <artifactId>commons-parent</artifactId> - <version>103</version> + <version>104</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>commons-dbutils</groupId> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 105e34c..4ff9f7e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -58,11 +58,12 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Gary Gregory">ResultSetIterator.next() now throws IllegalStateException instead of RuntimeException to wrap cases of SQLException.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">ResultSetIterator.remove() now throws IllegalStateException instead of RuntimeException to wrap cases of SQLException.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory, Matheus_Maas">org.apache.commons.dbutils.ResultSetIterator.next() now throws NoSuchElementException as defined in java.util.Iterator.next() #283.</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix SpotBugs USO_UNSAFE_METHOD_SYNCHRONIZATION in QueryLoader.</action> <!-- ADD --> <action type="add" dev="ggregory" due-to="strangelookingnerd, Gary Gregory">BaseResultSetHandler implements ResultSet.</action> <!-- UPDATE --> <action dev="ggregory" type="update" due-to="Gary Gregory">Bump Java from 8 to 11.</action> - <action dev="ggregory" type="update" due-to="Gary Gregory">Bump commons-parent from 62 to 102 #256, #277, #295, #301, #305, #308, #314, #387, #403, #406.</action> + <action dev="ggregory" type="update" due-to="Gary Gregory">Bump commons-parent from 62 to 104 #256, #277, #295, #301, #305, #308, #314, #387, #403, #406.</action> <action dev="ggregory" type="update" due-to="Dependabot, Gary Gregory">Bump org.mockito:mockito-junit-jupiter from 5.14.2 to 5.23.0 #336, #359, #366, #389, #408.</action> <action dev="ggregory" type="update" due-to="Dependabot, Gary Gregory">Bump commons-jxpath:commons-jxpath from 1.3 to 1.4.0 #360.</action> <action dev="ggregory" type="update" due-to="Dependabot, Gary Gregory">Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.20.0 #372.</action> diff --git a/src/main/java/org/apache/commons/dbutils/QueryLoader.java b/src/main/java/org/apache/commons/dbutils/QueryLoader.java index 023f973..ef7ea0f 100644 --- a/src/main/java/org/apache/commons/dbutils/QueryLoader.java +++ b/src/main/java/org/apache/commons/dbutils/QueryLoader.java @@ -22,6 +22,9 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; /** @@ -52,7 +55,7 @@ public class QueryLoader { /** * Maps query set names to Maps of their queries. */ - private final Map<String, Map<String, String>> queries = new HashMap<>(); + private final ConcurrentMap<String, Map<String, String>> queries = new ConcurrentHashMap<>(); /** * QueryLoader constructor. @@ -72,11 +75,18 @@ public class QueryLoader { * @return Map of query names to SQL values * @see java.util.Properties */ - public synchronized Map<String, String> load(final String path) throws IOException { - Map<String, String> queryMap = this.queries.get(path); - if (queryMap == null) { - queryMap = loadQueries(path); - this.queries.put(path, queryMap); + public Map<String, String> load(final String path) throws IOException { + final AtomicReference<IOException> ioe = new AtomicReference<>(); + final Map<String, String> queryMap = queries.computeIfAbsent(path, p -> { + try { + return loadQueries(p); + } catch (final IOException e) { + ioe.set(e); + return null; + } + }); + if (ioe.get() != null) { + throw ioe.get(); } return queryMap; } @@ -118,7 +128,7 @@ public class QueryLoader { * * @param path The path that the queries were loaded from. */ - public synchronized void unload(final String path) { - this.queries.remove(path); + public void unload(final String path) { + queries.remove(path); } }
