From a6c5526ab516ec84410fc889667b5716e5bc94f9 Mon Sep 17 00:00:00 2001 From: Morten Svanaes Date: Tue, 1 Sep 2026 01:04:07 +0800 Subject: [PATCH] perf: Bulk load option set options and restore entity cache [DHIS2-21905] Nested options on /api/optionSets loaded one collection per option set, and query-cache hits re-selected every OptionSet row because the entity-level cache was lost in the OptionSet.hbm.xml to JPA migration. - Restore the OptionSet entity L2 cache with an explicit ehcache region - Preload requested options collections with one cache-aware fetch-join query - Skip the preload entirely when the requested fields omit options --- .../org/hisp/dhis/option/OptionService.java | 9 + .../java/org/hisp/dhis/option/OptionSet.java | 1 + .../org/hisp/dhis/option/OptionSetStore.java | 51 ++++ .../org/hisp/dhis/config/StoreConfig.java | 7 - .../dhis/option/DefaultOptionService.java | 11 +- .../hibernate/HibernateOptionSetStore.java | 97 +++++++ .../src/main/resources/ehcache.xml | 7 + .../cache/HibernateEhcacheConfigFileTest.java | 12 + .../dhis/cache/HibernateQueryCacheTest.java | 37 ++- .../OptionSetControllerQueryCountTest.java | 247 ++++++++++++++++++ .../option/OptionSetController.java | 25 ++ 11 files changed, 491 insertions(+), 13 deletions(-) create mode 100644 dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSetStore.java create mode 100644 dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/option/hibernate/HibernateOptionSetStore.java create mode 100644 dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/option/OptionSetControllerQueryCountTest.java diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java index 9d94d7840e2f..98922c05315c 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java @@ -65,6 +65,15 @@ public interface OptionService { List getAllOptionSets(); + /** + * Initializes the {@link OptionSet#getOptions()} collections of the supplied managed option sets. + * Collections missing from the second-level cache are loaded together with one bulk query; + * collections present in the cache are initialized from it without SQL. + * + * @param optionSets managed option sets whose options collections should be initialized + */ + void preloadOptions(@Nonnull Collection optionSets); + List