
001/*- 002 * #%L 003 * HAPI FHIR JPA Model 004 * %% 005 * Copyright (C) 2014 - 2025 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.model.config; 021 022import ca.uhn.fhir.interceptor.model.IDefaultPartitionSettings; 023import ca.uhn.fhir.jpa.model.entity.StorageSettings; 024 025/** 026 * @since 5.0.0 027 */ 028public class PartitionSettings implements IDefaultPartitionSettings { 029 030 private boolean myPartitioningEnabled = false; 031 private CrossPartitionReferenceMode myAllowReferencesAcrossPartitions = CrossPartitionReferenceMode.NOT_ALLOWED; 032 private boolean myIncludePartitionInSearchHashes = false; 033 private boolean myUnnamedPartitionMode; 034 private Integer myDefaultPartitionId; 035 private boolean myAlwaysOpenNewTransactionForDifferentPartition; 036 private boolean myConditionalCreateDuplicateIdentifiersEnabled = false; 037 private boolean myDatabasePartitionMode = false; 038 039 public PartitionSettings() { 040 super(); 041 } 042 043 /** 044 * This flag activates partition IDs in PKs mode, which is newly introduced in HAPI FHIR 8.0.0. 045 * This mode causes partition IDs to be included in all primary keys, joins, and emitted 046 * SQL. It also affects the generated schema and migrations. This setting should not be changed 047 * after the database has been initialized, unless you have performed an appropriate migration. 048 * 049 * @since 8.0.0 050 */ 051 public boolean isDatabasePartitionMode() { 052 return myDatabasePartitionMode; 053 } 054 055 /** 056 * This flag activates partition IDs in PKs mode, which is newly introduced in HAPI FHIR 8.0.0. 057 * This mode causes partition IDs to be included in all primary keys, joins, and emitted 058 * SQL. It also affects the generated schema and migrations. This setting should not be changed 059 * after the database has been initialized, unless you have performed an appropriate migration. 060 * 061 * @since 8.0.0 062 */ 063 public PartitionSettings setDatabasePartitionMode(boolean theDatabasePartitionMode) { 064 myDatabasePartitionMode = theDatabasePartitionMode; 065 return this; 066 } 067 068 /** 069 * Should we always open a new database transaction if the partition context changes 070 * 071 * @since 6.6.0 072 */ 073 public boolean isAlwaysOpenNewTransactionForDifferentPartition() { 074 return myAlwaysOpenNewTransactionForDifferentPartition; 075 } 076 077 /** 078 * Should we always open a new database transaction if the partition context changes 079 * 080 * @since 6.6.0 081 */ 082 public PartitionSettings setAlwaysOpenNewTransactionForDifferentPartition( 083 boolean theAlwaysOpenNewTransactionForDifferentPartition) { 084 myAlwaysOpenNewTransactionForDifferentPartition = theAlwaysOpenNewTransactionForDifferentPartition; 085 return this; 086 } 087 088 /** 089 * If set to <code>true</code> (default is <code>false</code>) the <code>PARTITION_ID</code> value will be factored into the 090 * hash values used in the <code>HFJ_SPIDX_xxx</code> tables, removing the need to explicitly add a selector 091 * on this column in queries. If set to <code>false</code>, an additional selector is used instead, which may perform 092 * better when using native database partitioning features. 093 * <p> 094 * This setting has no effect if partitioning is not enabled via {@link #isPartitioningEnabled()}. 095 * </p> 096 * <p> 097 * If {@link StorageSettings#isIndexStorageOptimized()} is enabled this setting should be set to <code>false</code>. 098 * </p> 099 */ 100 public boolean isIncludePartitionInSearchHashes() { 101 return myIncludePartitionInSearchHashes; 102 } 103 104 /** 105 * If set to <code>true</code> (default is <code>false</code>) the <code>PARTITION_ID</code> value will be factored into the 106 * hash values used in the <code>HFJ_SPIDX_xxx</code> tables, removing the need to explicitly add a selector 107 * on this column in queries. If set to <code>false</code>, an additional selector is used instead, which may perform 108 * better when using native database partitioning features. 109 * <p> 110 * This setting has no effect if partitioning is not enabled via {@link #isPartitioningEnabled()}. 111 * </p> 112 * <p> 113 * If {@link StorageSettings#isIndexStorageOptimized()} is enabled this setting should be set to <code>false</code>. 114 * </p> 115 */ 116 public PartitionSettings setIncludePartitionInSearchHashes(boolean theIncludePartitionInSearchHashes) { 117 myIncludePartitionInSearchHashes = theIncludePartitionInSearchHashes; 118 return this; 119 } 120 121 /** 122 * If enabled (default is <code>false</code>) the JPA server will support data partitioning 123 * 124 * @since 5.0.0 125 */ 126 public boolean isPartitioningEnabled() { 127 return myPartitioningEnabled; 128 } 129 130 /** 131 * If enabled (default is <code>false</code>) the JPA server will support data partitioning 132 * 133 * @since 5.0.0 134 */ 135 public PartitionSettings setPartitioningEnabled(boolean theMultiTenancyEnabled) { 136 myPartitioningEnabled = theMultiTenancyEnabled; 137 return this; 138 } 139 140 /** 141 * Should resources references be permitted to cross partition boundaries. Default is {@link CrossPartitionReferenceMode#NOT_ALLOWED}. 142 * 143 * @since 5.0.0 144 */ 145 public CrossPartitionReferenceMode getAllowReferencesAcrossPartitions() { 146 return myAllowReferencesAcrossPartitions; 147 } 148 149 /** 150 * Should resources references be permitted to cross partition boundaries. Default is {@link CrossPartitionReferenceMode#NOT_ALLOWED}. 151 * 152 * @since 5.0.0 153 */ 154 public PartitionSettings setAllowReferencesAcrossPartitions( 155 CrossPartitionReferenceMode theAllowReferencesAcrossPartitions) { 156 myAllowReferencesAcrossPartitions = theAllowReferencesAcrossPartitions; 157 return this; 158 } 159 160 /** 161 * If set to <code>true</code> (default is <code>false</code>), partitions will be unnamed and all IDs from {@link Integer#MIN_VALUE} through 162 * {@link Integer#MAX_VALUE} will be allowed without needing to be created ahead of time. 163 * 164 * @since 5.5.0 165 */ 166 public boolean isUnnamedPartitionMode() { 167 return myUnnamedPartitionMode; 168 } 169 170 /** 171 * If set to <code>true</code> (default is <code>false</code>), partitions will be unnamed and all IDs from {@link Integer#MIN_VALUE} through 172 * {@link Integer#MAX_VALUE} will be allowed without needing to be created ahead of time. 173 * 174 * @since 5.5.0 175 */ 176 public PartitionSettings setUnnamedPartitionMode(boolean theUnnamedPartitionMode) { 177 myUnnamedPartitionMode = theUnnamedPartitionMode; 178 return this; 179 } 180 181 /** 182 * If set, the given ID will be used for the default partition. The default is 183 * <code>null</code> which will result in the use of a null value for default 184 * partition items. 185 * 186 * @since 5.5.0 187 */ 188 @Override 189 public Integer getDefaultPartitionId() { 190 return myDefaultPartitionId; 191 } 192 193 /** 194 * If set, the given ID will be used for the default partition. The default is 195 * <code>null</code> which will result in the use of a null value for default 196 * partition items. 197 * 198 * @since 5.5.0 199 */ 200 public PartitionSettings setDefaultPartitionId(Integer theDefaultPartitionId) { 201 myDefaultPartitionId = theDefaultPartitionId; 202 return this; 203 } 204 205 /** 206 * If enabled the JPA server will allow unqualified cross partition reference 207 */ 208 public boolean isAllowUnqualifiedCrossPartitionReference() { 209 return myAllowReferencesAcrossPartitions.equals( 210 PartitionSettings.CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED); 211 } 212 213 /** 214 * The {@link ca.uhn.fhir.jpa.model.entity.ResourceSearchUrlEntity} 215 * table is used to prevent accidental concurrent conditional create/update operations 216 * from creating duplicate resources by inserting a row in that table as a part 217 * of the database transaction performing the write operation. If this setting 218 * is set to {@literal false} (which is the default), the partition 219 * ID is not written to this table, meaning that duplicates are prevented across 220 * partitions. If this setting is {@literal true}, duplicates will not be 221 * prevented if they appear on different partitions. 222 */ 223 public boolean isConditionalCreateDuplicateIdentifiersEnabled() { 224 return myConditionalCreateDuplicateIdentifiersEnabled; 225 } 226 227 /** 228 * The {@link ca.uhn.fhir.jpa.model.entity.ResourceSearchUrlEntity} 229 * table is used to prevent accidental concurrent conditional create/update operations 230 * from creating duplicate resources by inserting a row in that table as a part 231 * of the database transaction performing the write operation. If this setting 232 * is set to {@literal false} (which is the default), the partition 233 * ID is not written to this table, meaning that duplicates are prevented across 234 * partitions. If this setting is {@literal true}, duplicates will not be 235 * prevented if they appear on different partitions. 236 */ 237 public PartitionSettings setConditionalCreateDuplicateIdentifiersEnabled( 238 boolean theConditionalCreateDuplicateIdentifiersEnabled) { 239 myConditionalCreateDuplicateIdentifiersEnabled = theConditionalCreateDuplicateIdentifiersEnabled; 240 return this; 241 } 242 243 public enum CrossPartitionReferenceMode { 244 245 /** 246 * References between resources are not allowed to cross partition boundaries 247 */ 248 NOT_ALLOWED, 249 250 /** 251 * References can cross partition boundaries, with an assumption that boundaries 252 * will be managed by the database. 253 */ 254 ALLOWED_UNQUALIFIED, 255 } 256}