From 0b81d5b1a16400b1522d01403cee68b07535e5e3 Mon Sep 17 00:00:00 2001 From: devmrko Date: Fri, 26 Jun 2026 06:07:27 +0900 Subject: [PATCH] fix #477: filter vpd targets by schema --- .../vpdbackoffice/mapper/VpdPolicyMapper.java | 2 +- .../service/VpdPolicyService.java | 18 +++++++++---- .../web/VpdPolicyController.java | 27 ++++++++++++++----- src/main/resources/mapper/VpdPolicyMapper.xml | 5 +++- .../templates/vpd-filter-policies.html | 27 +++++++++++++++++++ .../resources/templates/vpd-policies.html | 19 ++++++++++++- 6 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/VpdPolicyMapper.java b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/VpdPolicyMapper.java index 83a9136..a0b129e 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/VpdPolicyMapper.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/VpdPolicyMapper.java @@ -13,7 +13,7 @@ public interface VpdPolicyMapper { List findPolicies(); - List findVpdTargets(); + List findVpdTargets(@Param("owner") String owner); List findPolicyNameOptions(); diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java index e062a22..52bcd5e 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java @@ -12,7 +12,9 @@ import com.cloudhandson.vpdbackoffice.domain.vpd.VpdTargetView; import com.cloudhandson.vpdbackoffice.mapper.VpdPolicyMapper; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @@ -27,7 +29,7 @@ public class VpdPolicyService { private final VpdPolicyMapper mapper; private final JdbcTemplate jdbcTemplate; private final OpenAiCompatibleClient aiClient; - private volatile CacheEntry> vpdTargetsCache; + private final Map>> vpdTargetsCache = new ConcurrentHashMap<>(); private volatile CacheEntry formOptionsCache; public VpdPolicyService(VpdPolicyMapper mapper, JdbcTemplate jdbcTemplate, OpenAiCompatibleClient aiClient) { @@ -41,12 +43,18 @@ public class VpdPolicyService { } public List findVpdTargets() { - CacheEntry> cached = vpdTargetsCache; + return findVpdTargets(null); + } + + public List findVpdTargets(String owner) { + String normalizedOwner = normalizeOptionalIdentifier(owner); + String cacheKey = normalizedOwner == null ? "__MANAGED__" : normalizedOwner; + CacheEntry> cached = vpdTargetsCache.get(cacheKey); if (cached != null && !cached.expired()) { return cached.value(); } - List targets = List.copyOf(mapper.findVpdTargets()); - vpdTargetsCache = new CacheEntry<>(targets, System.currentTimeMillis() + CATALOG_CACHE_MILLIS); + List targets = List.copyOf(mapper.findVpdTargets(normalizedOwner)); + vpdTargetsCache.put(cacheKey, new CacheEntry<>(targets, System.currentTimeMillis() + CATALOG_CACHE_MILLIS)); return targets; } @@ -273,7 +281,7 @@ public class VpdPolicyService { } public void clearCatalogCache() { - vpdTargetsCache = null; + vpdTargetsCache.clear(); formOptionsCache = null; } diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java b/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java index 85767d1..704e286 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java @@ -22,27 +22,42 @@ public class VpdPolicyController { } @GetMapping("/vpd-policies") - public String policies(Model model) { - populatePolicyModel(model); + public String policies( + @RequestParam(required = false) String schemaOwner, + Model model + ) { + populatePolicyModel(schemaOwner, model); return "vpd-policies"; } @GetMapping("/vpd-filter-policies") - public String filterPolicies(Model model) { - populatePolicyModel(model); + public String filterPolicies( + @RequestParam(required = false) String schemaOwner, + Model model + ) { + populatePolicyModel(schemaOwner, model); return "vpd-filter-policies"; } - private void populatePolicyModel(Model model) { + private void populatePolicyModel(String schemaOwner, Model model) { try { + String selectedSchemaOwner = schemaOwner == null ? "" : schemaOwner.trim().toUpperCase(); model.addAttribute("policies", vpdPolicyService.findPolicies()); - model.addAttribute("vpdTargets", vpdPolicyService.findVpdTargets()); + model.addAttribute("vpdTargets", vpdPolicyService.findVpdTargets(selectedSchemaOwner)); + model.addAttribute("selectedSchemaOwner", selectedSchemaOwner); model.addAttribute("formOptions", vpdPolicyService.formOptions()); } catch (DataAccessException exception) { RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception); model.addAttribute("runtimeError", message); model.addAttribute("policies", List.of()); model.addAttribute("vpdTargets", List.of()); + model.addAttribute("selectedSchemaOwner", ""); + model.addAttribute("formOptions", vpdPolicyService.emptyFormOptions()); + } catch (AppException exception) { + model.addAttribute("errorMessage", exception.getMessage()); + model.addAttribute("policies", List.of()); + model.addAttribute("vpdTargets", List.of()); + model.addAttribute("selectedSchemaOwner", ""); model.addAttribute("formOptions", vpdPolicyService.emptyFormOptions()); } } diff --git a/src/main/resources/mapper/VpdPolicyMapper.xml b/src/main/resources/mapper/VpdPolicyMapper.xml index ccd9fd8..24f8e1d 100644 --- a/src/main/resources/mapper/VpdPolicyMapper.xml +++ b/src/main/resources/mapper/VpdPolicyMapper.xml @@ -48,7 +48,10 @@ SELECT owner, object_name, object_type FROM all_objects WHERE object_type IN ('TABLE', 'VIEW') - AND owner IN (SELECT owner FROM managed_owners) + AND ( + (#{owner,jdbcType=VARCHAR} IS NULL AND owner IN (SELECT owner FROM managed_owners)) + OR owner = UPPER(#{owner,jdbcType=VARCHAR}) + ) AND owner NOT IN ('SYS', 'SYSTEM', 'ORDS_METADATA', 'ORDS_PUBLIC_USER') AND owner NOT LIKE 'APEX\_%' ESCAPE '\' AND owner NOT LIKE 'C##%' diff --git a/src/main/resources/templates/vpd-filter-policies.html b/src/main/resources/templates/vpd-filter-policies.html index 7f030d3..ac3b7fe 100644 --- a/src/main/resources/templates/vpd-filter-policies.html +++ b/src/main/resources/templates/vpd-filter-policies.html @@ -16,6 +16,33 @@
등록되었습니다.
처리할 수 없습니다.
+
+
+
+

VPD 적용 대상 Schema

+

개별 적용 드롭다운에 표시할 TABLE/VIEW 스키마를 선택합니다.

+
+ 0 +
+
+ + +
+
+

Filter 등록/수정

diff --git a/src/main/resources/templates/vpd-policies.html b/src/main/resources/templates/vpd-policies.html index 59d29d4..30cd810 100644 --- a/src/main/resources/templates/vpd-policies.html +++ b/src/main/resources/templates/vpd-policies.html @@ -30,10 +30,27 @@

VPD 적용 대상 TABLE/VIEW

-

Oracle DB catalog 기준의 TABLE/VIEW 목록입니다. ORDS는 이 객체를 HTTP로 서빙하는 별도 레이어입니다.

+

Oracle DB catalog 기준의 TABLE/VIEW 목록입니다. Schema를 선택하면 해당 스키마 객체를 조회합니다.

0
+
+ + +