001package io.ebean.config;
002
003import com.fasterxml.jackson.core.JsonFactory;
004import io.avaje.config.Config;
005import io.ebean.*;
006import io.ebean.annotation.*;
007import io.ebean.cache.ServerCachePlugin;
008import io.ebean.config.dbplatform.DatabasePlatform;
009import io.ebean.config.dbplatform.DbEncrypt;
010import io.ebean.config.dbplatform.DbType;
011import io.ebean.config.dbplatform.IdType;
012import io.ebean.datasource.DataSourceConfig;
013import io.ebean.event.*;
014import io.ebean.event.changelog.ChangeLogListener;
015import io.ebean.event.changelog.ChangeLogPrepare;
016import io.ebean.event.changelog.ChangeLogRegister;
017import io.ebean.event.readaudit.ReadAuditLogger;
018import io.ebean.event.readaudit.ReadAuditPrepare;
019import io.ebean.util.StringHelper;
020
021import javax.persistence.EnumType;
022import javax.sql.DataSource;
023import java.time.Clock;
024import java.time.ZonedDateTime;
025import java.time.format.DateTimeFormatter;
026import java.util.*;
027
028/**
029 * The configuration used for creating a Database.
030 * <p>
031 * Used to programmatically construct an Database and optionally register it
032 * with the DB singleton.
033 * </p>
034 * <p>
035 * If you just use DB thout this programmatic configuration Ebean will read
036 * the application.properties file and take the configuration from there. This usually
037 * includes searching the class path and automatically registering any entity
038 * classes and listeners etc.
039 * </p>
040 * <pre>{@code
041 *
042 * DatabaseConfig config = new DatabaseConfig();
043 *
044 * // read the ebean.properties and load
045 * // those settings into this DatabaseConfig object
046 * config.loadFromProperties();
047 *
048 * // explicitly register the entity beans to avoid classpath scanning
049 * config.addClass(Customer.class);
050 * config.addClass(User.class);
051 *
052 * Database db = DatabaseFactory.create(config);
053 *
054 * }</pre>
055 *
056 * <p>
057 * Note that DatabaseConfigProvider provides a standard Java ServiceLoader mechanism that can
058 * be used to apply configuration to the DatabaseConfig.
059 * </p>
060 *
061 * @author emcgreal
062 * @author rbygrave
063 * @see DatabaseFactory
064 */
065public class DatabaseConfig {
066
067  /**
068   * The Database name.
069   */
070  private String name = "db";
071
072  /**
073   * Typically configuration type objects that are passed by this DatabaseConfig
074   * to plugins. For example - IgniteConfiguration passed to Ignite plugin.
075   */
076  private final Map<String, Object> serviceObject = new HashMap<>();
077
078  private ContainerConfig containerConfig;
079
080  /**
081   * The underlying properties that were used during configuration.
082   */
083  private Properties properties;
084
085  /**
086   * The resource directory.
087   */
088  private String resourceDirectory;
089
090  /**
091   * Set to true to register this Database with the DB singleton.
092   */
093  private boolean register = true;
094
095  /**
096   * Set to true if this is the default/primary database.
097   */
098  private boolean defaultServer = true;
099
100  /**
101   * Set this to true to disable class path search.
102   */
103  private boolean disableClasspathSearch;
104
105  private TenantMode tenantMode = TenantMode.NONE;
106
107  private String tenantPartitionColumn = "tenant_id";
108
109  private CurrentTenantProvider currentTenantProvider;
110
111  private TenantDataSourceProvider tenantDataSourceProvider;
112
113  private TenantSchemaProvider tenantSchemaProvider;
114
115  private TenantCatalogProvider tenantCatalogProvider;
116
117  /**
118   * When true will load entity classes via ModuleInfoLoader.
119   * <p>
120   * NB: ModuleInfoLoader implementations are generated by querybean generator.
121   * Having this on and registering entity classes means we don't need to manually
122   * write that code or use classpath scanning to find entity classes.
123   */
124  private boolean loadModuleInfo = true;
125
126  /**
127   * List of interesting classes such as entities, embedded, ScalarTypes,
128   * Listeners, Finders, Controllers etc.
129   */
130  private List<Class<?>> classes = new ArrayList<>();
131
132  /**
133   * The packages that are searched for interesting classes. Only used when
134   * classes is empty/not explicitly specified.
135   */
136  private List<String> packages = new ArrayList<>();
137
138  /**
139   * Configuration for the ElasticSearch integration.
140   */
141  private DocStoreConfig docStoreConfig = new DocStoreConfig();
142
143  /**
144   * Set to true when the Database only uses Document store.
145   */
146  private boolean docStoreOnly;
147
148  /**
149   * This is used to populate @WhoCreated, @WhoModified and
150   * support other audit features (who executed a query etc).
151   */
152  private CurrentUserProvider currentUserProvider;
153
154  /**
155   * Config controlling the AutoTune behaviour.
156   */
157  private AutoTuneConfig autoTuneConfig = new AutoTuneConfig();
158
159  /**
160   * The JSON format used for DateTime types. Default to millis.
161   */
162  private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.ISO8601;
163
164  /**
165   * The JSON format used for Date types. Default to millis.
166   */
167  private JsonConfig.Date jsonDate = JsonConfig.Date.ISO8601;
168
169  /**
170   * For writing JSON specify if null values or empty collections should be excluded.
171   * By default all values are included.
172   */
173  private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
174
175  /**
176   * The default mode used for {@code @DbJson} with Jackson ObjectMapper.
177   */
178  private MutationDetection jsonMutationDetection = MutationDetection.HASH;
179
180  /**
181   * The database platform name. Used to imply a DatabasePlatform to use.
182   */
183  private String databasePlatformName;
184
185  /**
186   * The database platform.
187   */
188  private DatabasePlatform databasePlatform;
189
190  /**
191   * JDBC fetchSize hint when using findList.  Defaults to 0 leaving it up to the JDBC driver.
192   */
193  private int jdbcFetchSizeFindList;
194
195  /**
196   * JDBC fetchSize hint when using findEach/findEachWhile.  Defaults to 100. Note that this does
197   * not apply to MySql as that gets special treatment (forward only etc).
198   */
199  private int jdbcFetchSizeFindEach = 100;
200
201  /**
202   * Suffix appended to the base table to derive the view that contains the union
203   * of the base table and the history table in order to support asOf queries.
204   */
205  private String asOfViewSuffix = "_with_history";
206
207  /**
208   * Column used to support history and 'As of' queries. This column is a timestamp range
209   * or equivalent.
210   */
211  private String asOfSysPeriod = "sys_period";
212
213  /**
214   * Suffix appended to the base table to derive the view that contains the union
215   * of the base table and the history table in order to support asOf queries.
216   */
217  private String historyTableSuffix = "_history";
218
219  /**
220   * When true explicit transactions beans that have been made dirty will be
221   * automatically persisted via update on flush.
222   */
223  private boolean autoPersistUpdates;
224
225  /**
226   * Use for transaction scoped batch mode.
227   */
228  private PersistBatch persistBatch = PersistBatch.NONE;
229
230  /**
231   * Use for cascade persist JDBC batch mode. INHERIT means use the platform default
232   * which is ALL except for SQL Server where it is NONE (as getGeneratedKeys isn't
233   * supported on SQL Server with JDBC batch).
234   */
235  private PersistBatch persistBatchOnCascade = PersistBatch.INHERIT;
236
237  private int persistBatchSize = 20;
238
239  private EnumType defaultEnumType = EnumType.ORDINAL;
240
241  private boolean disableLazyLoading;
242
243  /**
244   * The default batch size for lazy loading
245   */
246  private int lazyLoadBatchSize = 10;
247
248  /**
249   * The default batch size for 'query joins'.
250   */
251  private int queryBatchSize = 100;
252
253  private boolean eagerFetchLobs;
254
255  /**
256   * Timezone used to get/set Timestamp values via JDBC.
257   */
258  private String dataTimeZone;
259
260  private boolean ddlGenerate;
261
262  private boolean ddlRun;
263
264  private boolean ddlExtra = true;
265
266  private boolean ddlCreateOnly;
267
268  private String ddlInitSql;
269
270  private String ddlSeedSql;
271
272  private String ddlHeader;
273
274  /**
275   * Mode used to check non-null columns added via migration have a default value specified etc.
276   */
277  private boolean ddlStrictMode = true;
278
279  /**
280   * Comma and equals delimited key/value placeholders to replace in DDL scripts.
281   */
282  private String ddlPlaceholders;
283
284  /**
285   * Map of key/value placeholders to replace in DDL scripts.
286   */
287  private Map<String, String> ddlPlaceholderMap;
288
289  private boolean runMigration;
290
291  /**
292   * When true L2 bean cache use is skipped after a write has occurred on a transaction.
293   */
294  private boolean skipCacheAfterWrite = true;
295
296  private boolean useJtaTransactionManager;
297
298  /**
299   * The external transaction manager (like Spring).
300   */
301  private ExternalTransactionManager externalTransactionManager;
302
303  private boolean skipDataSourceCheck;
304
305  /**
306   * The data source (if programmatically provided).
307   */
308  private DataSource dataSource;
309
310  /**
311   * The read only data source (can be null).
312   */
313  private DataSource readOnlyDataSource;
314
315  /**
316   * The data source config.
317   */
318  private DataSourceConfig dataSourceConfig = new DataSourceConfig();
319
320  /**
321   * When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig.
322   * I believe this will default to true in some future release (as it has a nice performance benefit).
323   * <p>
324   * autoReadOnlyDataSource is an unfortunate name for this config option but I haven't come up with a better one.
325   */
326  private boolean autoReadOnlyDataSource;
327
328  /**
329   * Optional configuration for a read only data source.
330   */
331  private DataSourceConfig readOnlyDataSourceConfig = new DataSourceConfig();
332
333  /**
334   * Optional - the database schema that should be used to own the tables etc.
335   */
336  private String dbSchema;
337
338  /**
339   * The ClassLoadConfig used to detect Joda, Java8, Jackson etc and create plugin instances given a className.
340   */
341  private ClassLoadConfig classLoadConfig = new ClassLoadConfig();
342
343  /**
344   * The data source JNDI name if using a JNDI DataSource.
345   */
346  private String dataSourceJndiName;
347
348  /**
349   * The naming convention.
350   */
351  private NamingConvention namingConvention = new UnderscoreNamingConvention();
352
353  /**
354   * Behaviour of updates in JDBC batch to by default include all properties.
355   */
356  private boolean updateAllPropertiesInBatch;
357
358  /**
359   * Database platform configuration.
360   */
361  private PlatformConfig platformConfig = new PlatformConfig();
362
363  /**
364   * The UUID version to use.
365   */
366  private UuidVersion uuidVersion = UuidVersion.VERSION4;
367
368  /**
369   * The UUID state file (for Version 1 UUIDs). By default, the file is created in
370   * ${HOME}/.ebean/${servername}-uuid.state
371   */
372  private String uuidStateFile;
373
374  /**
375   * The clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
376   */
377  private Clock clock = Clock.systemUTC();
378
379  private List<IdGenerator> idGenerators = new ArrayList<>();
380  private List<BeanFindController> findControllers = new ArrayList<>();
381  private List<BeanPersistController> persistControllers = new ArrayList<>();
382  private List<BeanPostLoad> postLoaders = new ArrayList<>();
383  private List<BeanPostConstructListener> postConstructListeners = new ArrayList<>();
384  private List<BeanPersistListener> persistListeners = new ArrayList<>();
385  private List<BeanQueryAdapter> queryAdapters = new ArrayList<>();
386  private final List<BulkTableEventListener> bulkTableEventListeners = new ArrayList<>();
387  private final List<ServerConfigStartup> configStartupListeners = new ArrayList<>();
388
389  /**
390   * By default inserts are included in the change log.
391   */
392  private boolean changeLogIncludeInserts = true;
393
394  private ChangeLogPrepare changeLogPrepare;
395  private ChangeLogListener changeLogListener;
396  private ChangeLogRegister changeLogRegister;
397  private boolean changeLogAsync = true;
398  private ReadAuditLogger readAuditLogger;
399  private ReadAuditPrepare readAuditPrepare;
400  private EncryptKeyManager encryptKeyManager;
401  private EncryptDeployManager encryptDeployManager;
402  private Encryptor encryptor;
403  private DbEncrypt dbEncrypt;
404  private boolean dbOffline;
405  private ServerCachePlugin serverCachePlugin;
406
407  /**
408   * The default PersistenceContextScope used if one is not explicitly set on a query.
409   */
410  private PersistenceContextScope persistenceContextScope = PersistenceContextScope.TRANSACTION;
411  private JsonFactory jsonFactory;
412  private boolean localTimeWithNanos;
413  private boolean durationWithNanos;
414  private int maxCallStack = 5;
415  private boolean transactionRollbackOnChecked = true;
416
417  // configuration for the background executor service (thread pool)
418
419  private int backgroundExecutorSchedulePoolSize = 1;
420  private int backgroundExecutorShutdownSecs = 30;
421
422  // defaults for the L2 bean caching
423
424  private int cacheMaxSize = 10000;
425  private int cacheMaxIdleTime = 600;
426  private int cacheMaxTimeToLive = 60 * 60 * 6;
427
428  // defaults for the L2 query caching
429
430  private int queryCacheMaxSize = 1000;
431  private int queryCacheMaxIdleTime = 600;
432  private int queryCacheMaxTimeToLive = 60 * 60 * 6;
433  private Object objectMapper;
434
435  /**
436   * Set to true if you want eq("someProperty", null) to generate 1=1 rather than "is null" sql expression.
437   */
438  private boolean expressionEqualsWithNullAsNoop;
439
440  /**
441   * Set to true to use native ILIKE expression (if support by database platform / like Postgres).
442   */
443  private boolean expressionNativeIlike;
444
445  private String jodaLocalTimeMode;
446
447  /**
448   * Time to live for query plans - defaults to 5 minutes.
449   */
450  private int queryPlanTTLSeconds = 60 * 5;
451
452  /**
453   * Set to true to globally disable L2 caching (typically for performance testing).
454   */
455  private boolean disableL2Cache;
456
457  private String enabledL2Regions;
458
459  /**
460   * Set to true to effectively disable L2 cache plugins.
461   */
462  private boolean localOnlyL2Cache;
463
464  /**
465   * Should the javax.validation.constraints.NotNull enforce a notNull column in DB.
466   * If set to false, use io.ebean.annotation.NotNull or Column(nullable=true).
467   */
468  private boolean useValidationNotNull = true;
469
470  /**
471   * Generally we want to perform L2 cache notification in the background and not impact
472   * the performance of executing transactions.
473   */
474  private boolean notifyL2CacheInForeground;
475
476  /**
477   * Set to true to enable bind capture required for query plan capture.
478   */
479  private boolean queryPlanEnable;
480
481  /**
482   * The default threshold in micros for collecting query plans.
483   */
484  private long queryPlanThresholdMicros = Long.MAX_VALUE;
485
486  /**
487   * Set to true to enable automatic periodic query plan capture.
488   */
489  private boolean queryPlanCapture;
490  private long queryPlanCapturePeriodSecs = 60 * 10; // 10 minutes
491  private long queryPlanCaptureMaxTimeMillis = 10_000; // 10 seconds
492  private int queryPlanCaptureMaxCount = 10;
493  private QueryPlanListener queryPlanListener;
494
495  /**
496   * The time in millis used to determine when a query is alerted for being slow.
497   */
498  private long slowQueryMillis;
499
500  /**
501   * The listener for processing slow query events.
502   */
503  private SlowQueryListener slowQueryListener;
504
505  private ProfilingConfig profilingConfig = new ProfilingConfig();
506
507  /**
508   * Controls the default order by id setting of queries. See {@link Query#orderById(boolean)}
509   */
510  private boolean defaultOrderById;
511
512  /**
513   * The mappingLocations for searching xml mapping.
514   */
515  private List<String> mappingLocations = new ArrayList<>();
516
517  /**
518   * When true we do not need explicit GeneratedValue mapping.
519   */
520  private boolean idGeneratorAutomatic = true;
521
522  private boolean dumpMetricsOnShutdown;
523
524  private String dumpMetricsOptions;
525
526  /**
527   * Construct a Database Configuration for programmatically creating an Database.
528   */
529  public DatabaseConfig() {
530  }
531
532  /**
533   * Get the clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
534   */
535  public Clock getClock() {
536    return clock;
537  }
538
539  /**
540   * Set the clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
541   */
542  public void setClock(final Clock clock) {
543    this.clock = clock;
544  }
545
546  /**
547   * Return the slow query time in millis.
548   */
549  public long getSlowQueryMillis() {
550    return slowQueryMillis;
551  }
552
553  /**
554   * Set the slow query time in millis.
555   */
556  public void setSlowQueryMillis(long slowQueryMillis) {
557    this.slowQueryMillis = slowQueryMillis;
558  }
559
560  /**
561   * Return the slow query event listener.
562   */
563  public SlowQueryListener getSlowQueryListener() {
564    return slowQueryListener;
565  }
566
567  /**
568   * Set the slow query event listener.
569   */
570  public void setSlowQueryListener(SlowQueryListener slowQueryListener) {
571    this.slowQueryListener = slowQueryListener;
572  }
573
574
575  /**
576   * Deprecated - look to have explicit order by. Sets the default orderById setting for queries.
577   */
578  @Deprecated
579  public void setDefaultOrderById(boolean defaultOrderById) {
580    this.defaultOrderById = defaultOrderById;
581  }
582
583  /**
584   * Returns the default orderById setting for queries.
585   */
586  public boolean isDefaultOrderById() {
587    return defaultOrderById;
588  }
589
590  /**
591   * Put a service object into configuration such that it can be passed to a plugin.
592   * <p>
593   * For example, put IgniteConfiguration in to be passed to the Ignite plugin.
594   */
595  public void putServiceObject(String key, Object configObject) {
596    serviceObject.put(key, configObject);
597  }
598
599  /**
600   * Return the service object given the key.
601   */
602  public Object getServiceObject(String key) {
603    return serviceObject.get(key);
604  }
605
606  /**
607   * Put a service object into configuration such that it can be passed to a plugin.
608   *
609   * <pre>{@code
610   *
611   *   JedisPool jedisPool = ..
612   *
613   *   config.putServiceObject(jedisPool);
614   *
615   * }</pre>
616   */
617  public void putServiceObject(Object configObject) {
618    String key = serviceObjectKey(configObject);
619    serviceObject.put(key, configObject);
620  }
621
622  private String serviceObjectKey(Object configObject) {
623    return serviceObjectKey(configObject.getClass());
624  }
625
626  private String serviceObjectKey(Class<?> cls) {
627    String simpleName = cls.getSimpleName();
628    return Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
629  }
630
631  /**
632   * Used by plugins to obtain service objects.
633   *
634   * <pre>{@code
635   *
636   *   JedisPool jedisPool = config.getServiceObject(JedisPool.class);
637   *
638   * }</pre>
639   *
640   * @param cls The type of the service object to obtain
641   * @return The service object given the class type
642   */
643  @SuppressWarnings("unchecked")
644  public <P> P getServiceObject(Class<P> cls) {
645    return (P) serviceObject.get(serviceObjectKey(cls));
646  }
647
648  /**
649   * Return the Jackson JsonFactory to use.
650   * <p>
651   * If not set a default implementation will be used.
652   */
653  public JsonFactory getJsonFactory() {
654    return jsonFactory;
655  }
656
657  /**
658   * Set the Jackson JsonFactory to use.
659   * <p>
660   * If not set a default implementation will be used.
661   */
662  public void setJsonFactory(JsonFactory jsonFactory) {
663    this.jsonFactory = jsonFactory;
664  }
665
666  /**
667   * Return the JSON format used for DateTime types.
668   */
669  public JsonConfig.DateTime getJsonDateTime() {
670    return jsonDateTime;
671  }
672
673  /**
674   * Set the JSON format to use for DateTime types.
675   */
676  public void setJsonDateTime(JsonConfig.DateTime jsonDateTime) {
677    this.jsonDateTime = jsonDateTime;
678  }
679
680  /**
681   * Return the JSON format used for Date types.
682   */
683  public JsonConfig.Date getJsonDate() {
684    return jsonDate;
685  }
686
687  /**
688   * Set the JSON format to use for Date types.
689   */
690  public void setJsonDate(JsonConfig.Date jsonDate) {
691    this.jsonDate = jsonDate;
692  }
693
694  /**
695   * Return the JSON include mode used when writing JSON.
696   */
697  public JsonConfig.Include getJsonInclude() {
698    return jsonInclude;
699  }
700
701  /**
702   * Set the JSON include mode used when writing JSON.
703   * <p>
704   * Set to NON_NULL or NON_EMPTY to suppress nulls or null and empty collections respectively.
705   */
706  public void setJsonInclude(JsonConfig.Include jsonInclude) {
707    this.jsonInclude = jsonInclude;
708  }
709
710  /**
711   * Return the default MutableDetection to use with {@code @DbJson} using Jackson.
712   *
713   * @see DbJson#mutationDetection()
714   */
715  public MutationDetection getJsonMutationDetection() {
716    return jsonMutationDetection;
717  }
718
719  /**
720   * Set the default MutableDetection to use with {@code @DbJson} using Jackson.
721   *
722   * @see DbJson#mutationDetection()
723   */
724  public void setJsonMutationDetection(MutationDetection jsonMutationDetection) {
725    this.jsonMutationDetection = jsonMutationDetection;
726  }
727
728  /**
729   * Return the name of the Database.
730   */
731  public String getName() {
732    return name;
733  }
734
735  /**
736   * Set the name of the Database.
737   */
738  public void setName(String name) {
739    this.name = name;
740  }
741
742  /**
743   * Return the container / clustering configuration.
744   * <p/>
745   * The container holds all the Database instances and provides clustering communication
746   * services to all the Database instances.
747   */
748  public ContainerConfig getContainerConfig() {
749    return containerConfig;
750  }
751
752  /**
753   * Set the container / clustering configuration.
754   * <p/>
755   * The container holds all the Database instances and provides clustering communication
756   * services to all the Database instances.
757   */
758  public void setContainerConfig(ContainerConfig containerConfig) {
759    this.containerConfig = containerConfig;
760  }
761
762  /**
763   * Return true if this server should be registered with the Ebean singleton
764   * when it is created.
765   * <p>
766   * By default this is set to true.
767   */
768  public boolean isRegister() {
769    return register;
770  }
771
772  /**
773   * Set to false if you do not want this server to be registered with the Ebean
774   * singleton when it is created.
775   * <p>
776   * By default this is set to true.
777   */
778  public void setRegister(boolean register) {
779    this.register = register;
780  }
781
782  /**
783   * Return true if this server should be registered as the "default" server
784   * with the Ebean singleton.
785   * <p>
786   * This is only used when {@link #setRegister(boolean)} is also true.
787   */
788  public boolean isDefaultServer() {
789    return defaultServer;
790  }
791
792  /**
793   * Set false if you do not want this Database to be registered as the "default" database
794   * with the DB singleton.
795   * <p>
796   * This is only used when {@link #setRegister(boolean)} is also true.
797   */
798  public void setDefaultServer(boolean defaultServer) {
799    this.defaultServer = defaultServer;
800  }
801
802  /**
803   * Return the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
804   * support other audit features (who executed a query etc).
805   */
806  public CurrentUserProvider getCurrentUserProvider() {
807    return currentUserProvider;
808  }
809
810  /**
811   * Set the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
812   * support other audit features (who executed a query etc).
813   */
814  public void setCurrentUserProvider(CurrentUserProvider currentUserProvider) {
815    this.currentUserProvider = currentUserProvider;
816  }
817
818  /**
819   * Return the tenancy mode used.
820   */
821  public TenantMode getTenantMode() {
822    return tenantMode;
823  }
824
825  /**
826   * Set the tenancy mode to use.
827   */
828  public void setTenantMode(TenantMode tenantMode) {
829    this.tenantMode = tenantMode;
830  }
831
832  /**
833   * Return the column name used for TenantMode.PARTITION.
834   */
835  public String getTenantPartitionColumn() {
836    return tenantPartitionColumn;
837  }
838
839  /**
840   * Set the column name used for TenantMode.PARTITION.
841   */
842  public void setTenantPartitionColumn(String tenantPartitionColumn) {
843    this.tenantPartitionColumn = tenantPartitionColumn;
844  }
845
846  /**
847   * Return the current tenant provider.
848   */
849  public CurrentTenantProvider getCurrentTenantProvider() {
850    return currentTenantProvider;
851  }
852
853  /**
854   * Set the current tenant provider.
855   */
856  public void setCurrentTenantProvider(CurrentTenantProvider currentTenantProvider) {
857    this.currentTenantProvider = currentTenantProvider;
858  }
859
860  /**
861   * Return the tenancy datasource provider.
862   */
863  public TenantDataSourceProvider getTenantDataSourceProvider() {
864    return tenantDataSourceProvider;
865  }
866
867  /**
868   * Set the tenancy datasource provider.
869   */
870  public void setTenantDataSourceProvider(TenantDataSourceProvider tenantDataSourceProvider) {
871    this.tenantDataSourceProvider = tenantDataSourceProvider;
872  }
873
874  /**
875   * Return the tenancy schema provider.
876   */
877  public TenantSchemaProvider getTenantSchemaProvider() {
878    return tenantSchemaProvider;
879  }
880
881  /**
882   * Set the tenancy schema provider.
883   */
884  public void setTenantSchemaProvider(TenantSchemaProvider tenantSchemaProvider) {
885    this.tenantSchemaProvider = tenantSchemaProvider;
886  }
887
888  /**
889   * Return the tenancy catalog provider.
890   */
891  public TenantCatalogProvider getTenantCatalogProvider() {
892    return tenantCatalogProvider;
893  }
894
895  /**
896   * Set the tenancy catalog provider.
897   */
898  public void setTenantCatalogProvider(TenantCatalogProvider tenantCatalogProvider) {
899    this.tenantCatalogProvider = tenantCatalogProvider;
900  }
901
902  /**
903   * Return true if dirty beans are automatically persisted.
904   */
905  public boolean isAutoPersistUpdates() {
906    return autoPersistUpdates;
907  }
908
909  /**
910   * Set to true if dirty beans are automatically persisted.
911   */
912  public void setAutoPersistUpdates(boolean autoPersistUpdates) {
913    this.autoPersistUpdates = autoPersistUpdates;
914  }
915
916  /**
917   * Return the PersistBatch mode to use by default at the transaction level.
918   * <p>
919   * When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
920   * a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
921   * or the batch size is meet.
922   */
923  public PersistBatch getPersistBatch() {
924    return persistBatch;
925  }
926
927  /**
928   * Set the JDBC batch mode to use at the transaction level.
929   * <p>
930   * When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
931   * a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
932   * or the batch size is meet.
933   */
934  public void setPersistBatch(PersistBatch persistBatch) {
935    this.persistBatch = persistBatch;
936  }
937
938  /**
939   * Return the JDBC batch mode to use per save(), delete(), insert() or update() request.
940   * <p>
941   * This makes sense when a save() or delete() cascades and executes multiple child statements. The best case
942   * for this is when saving a master/parent bean this cascade inserts many detail/child beans.
943   * <p>
944   * This only takes effect when the persistBatch mode at the transaction level does not take effect.
945   */
946  public PersistBatch getPersistBatchOnCascade() {
947    return persistBatchOnCascade;
948  }
949
950  /**
951   * Set the JDBC batch mode to use per save(), delete(), insert() or update() request.
952   * <p>
953   * This makes sense when a save() or delete() etc cascades and executes multiple child statements. The best caase
954   * for this is when saving a master/parent bean this cascade inserts many detail/child beans.
955   * <p>
956   * This only takes effect when the persistBatch mode at the transaction level does not take effect.
957   */
958  public void setPersistBatchOnCascade(PersistBatch persistBatchOnCascade) {
959    this.persistBatchOnCascade = persistBatchOnCascade;
960  }
961
962  /**
963   * Deprecated, please migrate to using setPersistBatch().
964   * <p>
965   * Set to true if you what to use JDBC batching for persisting and deleting beans.
966   * <p>
967   * With this Ebean will batch up persist requests and use the JDBC batch api.
968   * This is a performance optimisation designed to reduce the network chatter.
969   * <p>
970   * When true this is equivalent to {@code setPersistBatch(PersistBatch.ALL)} or
971   * when false to {@code setPersistBatch(PersistBatch.NONE)}
972   */
973  public void setPersistBatching(boolean persistBatching) {
974    this.persistBatch = (persistBatching) ? PersistBatch.ALL : PersistBatch.NONE;
975  }
976
977  /**
978   * Return the batch size used for JDBC batching. This defaults to 20.
979   */
980  public int getPersistBatchSize() {
981    return persistBatchSize;
982  }
983
984  /**
985   * Set the batch size used for JDBC batching. If unset this defaults to 20.
986   * <p>
987   * You can also set the batch size on the transaction.
988   *
989   * @see Transaction#setBatchSize(int)
990   */
991  public void setPersistBatchSize(int persistBatchSize) {
992    this.persistBatchSize = persistBatchSize;
993  }
994
995  /**
996   * Gets the query batch size. This defaults to 100.
997   *
998   * @return the query batch size
999   */
1000  public int getQueryBatchSize() {
1001    return queryBatchSize;
1002  }
1003
1004  /**
1005   * Sets the query batch size. This defaults to 100.
1006   *
1007   * @param queryBatchSize the new query batch size
1008   */
1009  public void setQueryBatchSize(int queryBatchSize) {
1010    this.queryBatchSize = queryBatchSize;
1011  }
1012
1013  public EnumType getDefaultEnumType() {
1014    return defaultEnumType;
1015  }
1016
1017  public void setDefaultEnumType(EnumType defaultEnumType) {
1018    this.defaultEnumType = defaultEnumType;
1019  }
1020
1021  /**
1022   * Return true if lazy loading is disabled on queries by default.
1023   */
1024  public boolean isDisableLazyLoading() {
1025    return disableLazyLoading;
1026  }
1027
1028  /**
1029   * Set to true to disable lazy loading by default.
1030   * <p>
1031   * It can be turned on per query via {@link Query#setDisableLazyLoading(boolean)}.
1032   */
1033  public void setDisableLazyLoading(boolean disableLazyLoading) {
1034    this.disableLazyLoading = disableLazyLoading;
1035  }
1036
1037  /**
1038   * Return the default batch size for lazy loading of beans and collections.
1039   */
1040  public int getLazyLoadBatchSize() {
1041    return lazyLoadBatchSize;
1042  }
1043
1044  /**
1045   * Set the default batch size for lazy loading.
1046   * <p>
1047   * This is the number of beans or collections loaded when lazy loading is
1048   * invoked by default.
1049   * <p>
1050   * The default value is for this is 10 (load 10 beans or collections).
1051   * <p>
1052   * You can explicitly control the lazy loading batch size for a given join on
1053   * a query using +lazy(batchSize) or JoinConfig.
1054   */
1055  public void setLazyLoadBatchSize(int lazyLoadBatchSize) {
1056    this.lazyLoadBatchSize = lazyLoadBatchSize;
1057  }
1058
1059  /**
1060   * Set the number of sequences to fetch/preallocate when using DB sequences.
1061   * <p>
1062   * This is a performance optimisation to reduce the number times Ebean
1063   * requests a sequence to be used as an Id for a bean (aka reduce network
1064   * chatter).
1065   */
1066  public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
1067    platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
1068  }
1069
1070  /**
1071   * Return the default JDBC fetchSize hint for findList queries.
1072   */
1073  public int getJdbcFetchSizeFindList() {
1074    return jdbcFetchSizeFindList;
1075  }
1076
1077  /**
1078   * Set the default JDBC fetchSize hint for findList queries.
1079   */
1080  public void setJdbcFetchSizeFindList(int jdbcFetchSizeFindList) {
1081    this.jdbcFetchSizeFindList = jdbcFetchSizeFindList;
1082  }
1083
1084  /**
1085   * Return the default JDBC fetchSize hint for findEach/findEachWhile queries.
1086   */
1087  public int getJdbcFetchSizeFindEach() {
1088    return jdbcFetchSizeFindEach;
1089  }
1090
1091  /**
1092   * Set the default JDBC fetchSize hint for findEach/findEachWhile queries.
1093   */
1094  public void setJdbcFetchSizeFindEach(int jdbcFetchSizeFindEach) {
1095    this.jdbcFetchSizeFindEach = jdbcFetchSizeFindEach;
1096  }
1097
1098  /**
1099   * Return the ChangeLogPrepare.
1100   * <p>
1101   * This is used to set user context information to the ChangeSet in the
1102   * foreground thread prior to the logging occurring in a background thread.
1103   */
1104  public ChangeLogPrepare getChangeLogPrepare() {
1105    return changeLogPrepare;
1106  }
1107
1108  /**
1109   * Set the ChangeLogPrepare.
1110   * <p>
1111   * This is used to set user context information to the ChangeSet in the
1112   * foreground thread prior to the logging occurring in a background thread.
1113   */
1114  public void setChangeLogPrepare(ChangeLogPrepare changeLogPrepare) {
1115    this.changeLogPrepare = changeLogPrepare;
1116  }
1117
1118  /**
1119   * Return the ChangeLogListener which actually performs the logging of change sets
1120   * in the background.
1121   */
1122  public ChangeLogListener getChangeLogListener() {
1123    return changeLogListener;
1124  }
1125
1126  /**
1127   * Set the ChangeLogListener which actually performs the logging of change sets
1128   * in the background.
1129   */
1130  public void setChangeLogListener(ChangeLogListener changeLogListener) {
1131    this.changeLogListener = changeLogListener;
1132  }
1133
1134  /**
1135   * Return the ChangeLogRegister which controls which ChangeLogFilter is used for each
1136   * bean type and in this way provide fine grained control over which persist requests
1137   * are included in the change log.
1138   */
1139  public ChangeLogRegister getChangeLogRegister() {
1140    return changeLogRegister;
1141  }
1142
1143  /**
1144   * Set the ChangeLogRegister which controls which ChangeLogFilter is used for each
1145   * bean type and in this way provide fine grained control over which persist requests
1146   * are included in the change log.
1147   */
1148  public void setChangeLogRegister(ChangeLogRegister changeLogRegister) {
1149    this.changeLogRegister = changeLogRegister;
1150  }
1151
1152  /**
1153   * Return true if inserts should be included in the change log by default.
1154   */
1155  public boolean isChangeLogIncludeInserts() {
1156    return changeLogIncludeInserts;
1157  }
1158
1159  /**
1160   * Set if inserts should be included in the change log by default.
1161   */
1162  public void setChangeLogIncludeInserts(boolean changeLogIncludeInserts) {
1163    this.changeLogIncludeInserts = changeLogIncludeInserts;
1164  }
1165
1166  /**
1167   * Return true (default) if the changelog should be written async.
1168   */
1169  public boolean isChangeLogAsync() {
1170    return changeLogAsync;
1171  }
1172
1173  /**
1174   * Sets if the changelog should be written async (default = true).
1175   */
1176  public void setChangeLogAsync(boolean changeLogAsync) {
1177    this.changeLogAsync = changeLogAsync;
1178  }
1179
1180  /**
1181   * Return the ReadAuditLogger to use.
1182   */
1183  public ReadAuditLogger getReadAuditLogger() {
1184    return readAuditLogger;
1185  }
1186
1187  /**
1188   * Set the ReadAuditLogger to use. If not set the default implementation is used
1189   * which logs the read events in JSON format to a standard named SLF4J logger
1190   * (which can be configured in say logback to log to a separate log file).
1191   */
1192  public void setReadAuditLogger(ReadAuditLogger readAuditLogger) {
1193    this.readAuditLogger = readAuditLogger;
1194  }
1195
1196  /**
1197   * Return the ReadAuditPrepare to use.
1198   */
1199  public ReadAuditPrepare getReadAuditPrepare() {
1200    return readAuditPrepare;
1201  }
1202
1203  /**
1204   * Set the ReadAuditPrepare to use.
1205   * <p>
1206   * It is expected that an implementation is used that read user context information
1207   * (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
1208   * to the ReadAuditLogger.
1209   */
1210  public void setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
1211    this.readAuditPrepare = readAuditPrepare;
1212  }
1213
1214  /**
1215   * Return the configuration for profiling.
1216   */
1217  public ProfilingConfig getProfilingConfig() {
1218    return profilingConfig;
1219  }
1220
1221  /**
1222   * Set the configuration for profiling.
1223   */
1224  public void setProfilingConfig(ProfilingConfig profilingConfig) {
1225    this.profilingConfig = profilingConfig;
1226  }
1227
1228  /**
1229   * Return the DB schema to use.
1230   */
1231  public String getDbSchema() {
1232    return dbSchema;
1233  }
1234
1235  /**
1236   * Set the DB schema to use. This specifies to use this schema for:
1237   * <ul>
1238   * <li>Running Database migrations - Create and use the DB schema</li>
1239   * <li>Testing DDL - Create-all.sql DDL execution creates and uses schema</li>
1240   * <li>Testing Docker - Set default schema on connection URL</li>
1241   * </ul>
1242   */
1243  public void setDbSchema(String dbSchema) {
1244    this.dbSchema = dbSchema;
1245  }
1246
1247  /**
1248   * Return the Geometry SRID.
1249   */
1250  public int getGeometrySRID() {
1251    return platformConfig.getGeometrySRID();
1252  }
1253
1254  /**
1255   * Set the Geometry SRID.
1256   */
1257  public void setGeometrySRID(int geometrySRID) {
1258    platformConfig.setGeometrySRID(geometrySRID);
1259  }
1260
1261  /**
1262   * Return the time zone to use when reading/writing Timestamps via JDBC.
1263   * <p>
1264   * When set a Calendar object is used in JDBC calls when reading/writing Timestamp objects.
1265   */
1266  public String getDataTimeZone() {
1267    return System.getProperty("ebean.dataTimeZone", dataTimeZone);
1268  }
1269
1270  /**
1271   * Set the time zone to use when reading/writing Timestamps via JDBC.
1272   */
1273  public void setDataTimeZone(String dataTimeZone) {
1274    this.dataTimeZone = dataTimeZone;
1275  }
1276
1277  /**
1278   * Return the suffix appended to the base table to derive the view that contains the union
1279   * of the base table and the history table in order to support asOf queries.
1280   */
1281  public String getAsOfViewSuffix() {
1282    return asOfViewSuffix;
1283  }
1284
1285  /**
1286   * Set the suffix appended to the base table to derive the view that contains the union
1287   * of the base table and the history table in order to support asOf queries.
1288   */
1289  public void setAsOfViewSuffix(String asOfViewSuffix) {
1290    this.asOfViewSuffix = asOfViewSuffix;
1291  }
1292
1293  /**
1294   * Return the database column used to support history and 'As of' queries. This column is a timestamp range
1295   * or equivalent.
1296   */
1297  public String getAsOfSysPeriod() {
1298    return asOfSysPeriod;
1299  }
1300
1301  /**
1302   * Set the database column used to support history and 'As of' queries. This column is a timestamp range
1303   * or equivalent.
1304   */
1305  public void setAsOfSysPeriod(String asOfSysPeriod) {
1306    this.asOfSysPeriod = asOfSysPeriod;
1307  }
1308
1309  /**
1310   * Return the history table suffix (defaults to _history).
1311   */
1312  public String getHistoryTableSuffix() {
1313    return historyTableSuffix;
1314  }
1315
1316  /**
1317   * Set the history table suffix.
1318   */
1319  public void setHistoryTableSuffix(String historyTableSuffix) {
1320    this.historyTableSuffix = historyTableSuffix;
1321  }
1322
1323  /**
1324   * Return true if we are running in a JTA Transaction manager.
1325   */
1326  public boolean isUseJtaTransactionManager() {
1327    return useJtaTransactionManager;
1328  }
1329
1330  /**
1331   * Set to true if we are running in a JTA Transaction manager.
1332   */
1333  public void setUseJtaTransactionManager(boolean useJtaTransactionManager) {
1334    this.useJtaTransactionManager = useJtaTransactionManager;
1335  }
1336
1337  /**
1338   * Return the external transaction manager.
1339   */
1340  public ExternalTransactionManager getExternalTransactionManager() {
1341    return externalTransactionManager;
1342  }
1343
1344  /**
1345   * Set the external transaction manager.
1346   */
1347  public void setExternalTransactionManager(ExternalTransactionManager externalTransactionManager) {
1348    this.externalTransactionManager = externalTransactionManager;
1349  }
1350
1351  /**
1352   * Return the ServerCachePlugin.
1353   */
1354  public ServerCachePlugin getServerCachePlugin() {
1355    return serverCachePlugin;
1356  }
1357
1358  /**
1359   * Set the ServerCachePlugin to use.
1360   */
1361  public void setServerCachePlugin(ServerCachePlugin serverCachePlugin) {
1362    this.serverCachePlugin = serverCachePlugin;
1363  }
1364
1365  /**
1366   * Return true if LOB's should default to fetch eager.
1367   * By default this is set to false and LOB's must be explicitly fetched.
1368   */
1369  public boolean isEagerFetchLobs() {
1370    return eagerFetchLobs;
1371  }
1372
1373  /**
1374   * Set to true if you want LOB's to be fetch eager by default.
1375   * By default this is set to false and LOB's must be explicitly fetched.
1376   */
1377  public void setEagerFetchLobs(boolean eagerFetchLobs) {
1378    this.eagerFetchLobs = eagerFetchLobs;
1379  }
1380
1381  /**
1382   * Return the max call stack to use for origin location.
1383   */
1384  public int getMaxCallStack() {
1385    return maxCallStack;
1386  }
1387
1388  /**
1389   * Set the max call stack to use for origin location.
1390   */
1391  public void setMaxCallStack(int maxCallStack) {
1392    this.maxCallStack = maxCallStack;
1393  }
1394
1395  /**
1396   * Return true if transactions should rollback on checked exceptions.
1397   */
1398  public boolean isTransactionRollbackOnChecked() {
1399    return transactionRollbackOnChecked;
1400  }
1401
1402  /**
1403   * Set to true if transactions should by default rollback on checked exceptions.
1404   */
1405  public void setTransactionRollbackOnChecked(boolean transactionRollbackOnChecked) {
1406    this.transactionRollbackOnChecked = transactionRollbackOnChecked;
1407  }
1408
1409  /**
1410   * Return the Background executor schedule pool size. Defaults to 1.
1411   */
1412  public int getBackgroundExecutorSchedulePoolSize() {
1413    return backgroundExecutorSchedulePoolSize;
1414  }
1415
1416  /**
1417   * Set the Background executor schedule pool size.
1418   */
1419  public void setBackgroundExecutorSchedulePoolSize(int backgroundExecutorSchedulePoolSize) {
1420    this.backgroundExecutorSchedulePoolSize = backgroundExecutorSchedulePoolSize;
1421  }
1422
1423  /**
1424   * Return the Background executor shutdown seconds. This is the time allowed for the pool to shutdown nicely
1425   * before it is forced shutdown.
1426   */
1427  public int getBackgroundExecutorShutdownSecs() {
1428    return backgroundExecutorShutdownSecs;
1429  }
1430
1431  /**
1432   * Set the Background executor shutdown seconds. This is the time allowed for the pool to shutdown nicely
1433   * before it is forced shutdown.
1434   */
1435  public void setBackgroundExecutorShutdownSecs(int backgroundExecutorShutdownSecs) {
1436    this.backgroundExecutorShutdownSecs = backgroundExecutorShutdownSecs;
1437  }
1438
1439  /**
1440   * Return the L2 cache default max size.
1441   */
1442  public int getCacheMaxSize() {
1443    return cacheMaxSize;
1444  }
1445
1446  /**
1447   * Set the L2 cache default max size.
1448   */
1449  public void setCacheMaxSize(int cacheMaxSize) {
1450    this.cacheMaxSize = cacheMaxSize;
1451  }
1452
1453  /**
1454   * Return the L2 cache default max idle time in seconds.
1455   */
1456  public int getCacheMaxIdleTime() {
1457    return cacheMaxIdleTime;
1458  }
1459
1460  /**
1461   * Set the L2 cache default max idle time in seconds.
1462   */
1463  public void setCacheMaxIdleTime(int cacheMaxIdleTime) {
1464    this.cacheMaxIdleTime = cacheMaxIdleTime;
1465  }
1466
1467  /**
1468   * Return the L2 cache default max time to live in seconds.
1469   */
1470  public int getCacheMaxTimeToLive() {
1471    return cacheMaxTimeToLive;
1472  }
1473
1474  /**
1475   * Set the L2 cache default max time to live in seconds.
1476   */
1477  public void setCacheMaxTimeToLive(int cacheMaxTimeToLive) {
1478    this.cacheMaxTimeToLive = cacheMaxTimeToLive;
1479  }
1480
1481  /**
1482   * Return the L2 query cache default max size.
1483   */
1484  public int getQueryCacheMaxSize() {
1485    return queryCacheMaxSize;
1486  }
1487
1488  /**
1489   * Set the L2 query cache default max size.
1490   */
1491  public void setQueryCacheMaxSize(int queryCacheMaxSize) {
1492    this.queryCacheMaxSize = queryCacheMaxSize;
1493  }
1494
1495  /**
1496   * Return the L2 query cache default max idle time in seconds.
1497   */
1498  public int getQueryCacheMaxIdleTime() {
1499    return queryCacheMaxIdleTime;
1500  }
1501
1502  /**
1503   * Set the L2 query cache default max idle time in seconds.
1504   */
1505  public void setQueryCacheMaxIdleTime(int queryCacheMaxIdleTime) {
1506    this.queryCacheMaxIdleTime = queryCacheMaxIdleTime;
1507  }
1508
1509  /**
1510   * Return the L2 query cache default max time to live in seconds.
1511   */
1512  public int getQueryCacheMaxTimeToLive() {
1513    return queryCacheMaxTimeToLive;
1514  }
1515
1516  /**
1517   * Set the L2 query cache default max time to live in seconds.
1518   */
1519  public void setQueryCacheMaxTimeToLive(int queryCacheMaxTimeToLive) {
1520    this.queryCacheMaxTimeToLive = queryCacheMaxTimeToLive;
1521  }
1522
1523  /**
1524   * Return the NamingConvention.
1525   * <p>
1526   * If none has been set the default UnderscoreNamingConvention is used.
1527   */
1528  public NamingConvention getNamingConvention() {
1529    return namingConvention;
1530  }
1531
1532  /**
1533   * Set the NamingConvention.
1534   * <p>
1535   * If none is set the default UnderscoreNamingConvention is used.
1536   */
1537  public void setNamingConvention(NamingConvention namingConvention) {
1538    this.namingConvention = namingConvention;
1539  }
1540
1541  /**
1542   * Return true if all DB column and table names should use quoted identifiers.
1543   */
1544  public boolean isAllQuotedIdentifiers() {
1545    return platformConfig.isAllQuotedIdentifiers();
1546  }
1547
1548  /**
1549   * Set to true if all DB column and table names should use quoted identifiers.
1550   */
1551  public void setAllQuotedIdentifiers(boolean allQuotedIdentifiers) {
1552    platformConfig.setAllQuotedIdentifiers(allQuotedIdentifiers);
1553    if (allQuotedIdentifiers) {
1554      adjustNamingConventionForAllQuoted();
1555    }
1556  }
1557
1558  private void adjustNamingConventionForAllQuoted() {
1559    if (namingConvention instanceof UnderscoreNamingConvention) {
1560      // we need to use matching naming convention
1561      this.namingConvention = new MatchingNamingConvention();
1562    }
1563  }
1564
1565  /**
1566   * Return true if this Database is a Document store only instance (has no JDBC DB).
1567   */
1568  public boolean isDocStoreOnly() {
1569    return docStoreOnly;
1570  }
1571
1572  /**
1573   * Set to true if this Database is Document store only instance (has no JDBC DB).
1574   */
1575  public void setDocStoreOnly(boolean docStoreOnly) {
1576    this.docStoreOnly = docStoreOnly;
1577  }
1578
1579  /**
1580   * Return the configuration for the ElasticSearch integration.
1581   */
1582  public DocStoreConfig getDocStoreConfig() {
1583    return docStoreConfig;
1584  }
1585
1586  /**
1587   * Set the configuration for the ElasticSearch integration.
1588   */
1589  public void setDocStoreConfig(DocStoreConfig docStoreConfig) {
1590    this.docStoreConfig = docStoreConfig;
1591  }
1592
1593  /**
1594   * Return the constraint naming convention used in DDL generation.
1595   */
1596  public DbConstraintNaming getConstraintNaming() {
1597    return platformConfig.getConstraintNaming();
1598  }
1599
1600  /**
1601   * Set the constraint naming convention used in DDL generation.
1602   */
1603  public void setConstraintNaming(DbConstraintNaming constraintNaming) {
1604    platformConfig.setConstraintNaming(constraintNaming);
1605  }
1606
1607  /**
1608   * Return the configuration for AutoTune.
1609   */
1610  public AutoTuneConfig getAutoTuneConfig() {
1611    return autoTuneConfig;
1612  }
1613
1614  /**
1615   * Set the configuration for AutoTune.
1616   */
1617  public void setAutoTuneConfig(AutoTuneConfig autoTuneConfig) {
1618    this.autoTuneConfig = autoTuneConfig;
1619  }
1620
1621  /**
1622   * Return true if the startup DataSource check should be skipped.
1623   */
1624  public boolean skipDataSourceCheck() {
1625    return skipDataSourceCheck;
1626  }
1627
1628  /**
1629   * Set to true to skip the startup DataSource check.
1630   */
1631  public void setSkipDataSourceCheck(boolean skipDataSourceCheck) {
1632    this.skipDataSourceCheck = skipDataSourceCheck;
1633  }
1634
1635  /**
1636   * Return the DataSource.
1637   */
1638  public DataSource getDataSource() {
1639    return dataSource;
1640  }
1641
1642  /**
1643   * Set a DataSource.
1644   */
1645  public void setDataSource(DataSource dataSource) {
1646    this.dataSource = dataSource;
1647  }
1648
1649  /**
1650   * Return the read only DataSource.
1651   */
1652  public DataSource getReadOnlyDataSource() {
1653    return readOnlyDataSource;
1654  }
1655
1656  /**
1657   * Set the read only DataSource.
1658   * <p>
1659   * Note that the DataSource is expected to use AutoCommit true mode avoiding the need
1660   * for explicit commit (or rollback).
1661   * <p>
1662   * This read only DataSource will be used for implicit query only transactions. It is not
1663   * used if the transaction is created explicitly or if the query is an update or delete query.
1664   */
1665  public void setReadOnlyDataSource(DataSource readOnlyDataSource) {
1666    this.readOnlyDataSource = readOnlyDataSource;
1667  }
1668
1669  /**
1670   * Return the configuration to build a DataSource using Ebean's own DataSource
1671   * implementation.
1672   */
1673  public DataSourceConfig getDataSourceConfig() {
1674    return dataSourceConfig;
1675  }
1676
1677  /**
1678   * Set the configuration required to build a DataSource using Ebean's own
1679   * DataSource implementation.
1680   */
1681  public void setDataSourceConfig(DataSourceConfig dataSourceConfig) {
1682    this.dataSourceConfig = dataSourceConfig;
1683  }
1684
1685  /**
1686   * Return true if Ebean should create a DataSource for use with implicit read only transactions.
1687   */
1688  public boolean isAutoReadOnlyDataSource() {
1689    return autoReadOnlyDataSource;
1690  }
1691
1692  /**
1693   * Set to true if Ebean should create a DataSource for use with implicit read only transactions.
1694   */
1695  public void setAutoReadOnlyDataSource(boolean autoReadOnlyDataSource) {
1696    this.autoReadOnlyDataSource = autoReadOnlyDataSource;
1697  }
1698
1699  /**
1700   * Return the configuration for the read only DataSource.
1701   * <p>
1702   * This is only used if autoReadOnlyDataSource is true.
1703   * <p>
1704   * The driver, url, username and password default to the configuration for the main DataSource if they are not
1705   * set on this configuration. This means there is actually no need to set any configuration here and we only
1706   * set configuration for url, username and password etc if it is different from the main DataSource.
1707   */
1708  public DataSourceConfig getReadOnlyDataSourceConfig() {
1709    return readOnlyDataSourceConfig;
1710  }
1711
1712  /**
1713   * Set the configuration for the read only DataSource.
1714   */
1715  public void setReadOnlyDataSourceConfig(DataSourceConfig readOnlyDataSourceConfig) {
1716    this.readOnlyDataSourceConfig = readOnlyDataSourceConfig;
1717  }
1718
1719  /**
1720   * Return the JNDI name of the DataSource to use.
1721   */
1722  public String getDataSourceJndiName() {
1723    return dataSourceJndiName;
1724  }
1725
1726  /**
1727   * Set the JNDI name of the DataSource to use.
1728   * <p>
1729   * By default a prefix of "java:comp/env/jdbc/" is used to lookup the
1730   * DataSource. This prefix is not used if dataSourceJndiName starts with
1731   * "java:".
1732   */
1733  public void setDataSourceJndiName(String dataSourceJndiName) {
1734    this.dataSourceJndiName = dataSourceJndiName;
1735  }
1736
1737  /**
1738   * Return a value used to represent TRUE in the database.
1739   * <p>
1740   * This is used for databases that do not support boolean natively.
1741   * <p>
1742   * The value returned is either a Integer or a String (e.g. "1", or "T").
1743   */
1744  public String getDatabaseBooleanTrue() {
1745    return platformConfig.getDatabaseBooleanTrue();
1746  }
1747
1748  /**
1749   * Set the value to represent TRUE in the database.
1750   * <p>
1751   * This is used for databases that do not support boolean natively.
1752   * <p>
1753   * The value set is either a Integer or a String (e.g. "1", or "T").
1754   */
1755  public void setDatabaseBooleanTrue(String databaseTrue) {
1756    platformConfig.setDatabaseBooleanTrue(databaseTrue);
1757  }
1758
1759  /**
1760   * Return a value used to represent FALSE in the database.
1761   * <p>
1762   * This is used for databases that do not support boolean natively.
1763   * <p>
1764   * The value returned is either a Integer or a String (e.g. "0", or "F").
1765   */
1766  public String getDatabaseBooleanFalse() {
1767    return platformConfig.getDatabaseBooleanFalse();
1768  }
1769
1770  /**
1771   * Set the value to represent FALSE in the database.
1772   * <p>
1773   * This is used for databases that do not support boolean natively.
1774   * <p>
1775   * The value set is either a Integer or a String (e.g. "0", or "F").
1776   */
1777  public void setDatabaseBooleanFalse(String databaseFalse) {
1778    this.platformConfig.setDatabaseBooleanFalse(databaseFalse);
1779  }
1780
1781  /**
1782   * Return the number of DB sequence values that should be preallocated.
1783   */
1784  public int getDatabaseSequenceBatchSize() {
1785    return platformConfig.getDatabaseSequenceBatchSize();
1786  }
1787
1788  /**
1789   * Set the number of DB sequence values that should be preallocated and cached
1790   * by Ebean.
1791   * <p>
1792   * This is only used for DB's that use sequences and is a performance
1793   * optimisation. This reduces the number of times Ebean needs to get a
1794   * sequence value from the Database reducing network chatter.
1795   * <p>
1796   * By default this value is 10 so when we need another Id (and don't have one
1797   * in our cache) Ebean will fetch 10 id's from the database. Note that when
1798   * the cache drops to have full (which is 5 by default) Ebean will fetch
1799   * another batch of Id's in a background thread.
1800   */
1801  public void setDatabaseSequenceBatch(int databaseSequenceBatchSize) {
1802    this.platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
1803  }
1804
1805  /**
1806   * Return the database platform name (can be null).
1807   * <p>
1808   * If null then the platform is determined automatically via the JDBC driver
1809   * information.
1810   */
1811  public String getDatabasePlatformName() {
1812    return databasePlatformName;
1813  }
1814
1815  /**
1816   * Explicitly set the database platform name
1817   * <p>
1818   * If none is set then the platform is determined automatically via the JDBC
1819   * driver information.
1820   * <p>
1821   * This can be used when the Database Platform can not be automatically
1822   * detected from the JDBC driver (possibly 3rd party JDBC driver). It is also
1823   * useful when you want to do offline DDL generation for a database platform
1824   * that you don't have access to.
1825   * <p>
1826   * Values are oracle, h2, postgres, mysql, sqlserver16, sqlserver17.
1827   */
1828  public void setDatabasePlatformName(String databasePlatformName) {
1829    this.databasePlatformName = databasePlatformName;
1830  }
1831
1832  /**
1833   * Return the database platform to use for this database.
1834   */
1835  public DatabasePlatform getDatabasePlatform() {
1836    return databasePlatform;
1837  }
1838
1839  /**
1840   * Explicitly set the database platform to use.
1841   * <p>
1842   * If none is set then the platform is determined via the databasePlatformName
1843   * or automatically via the JDBC driver information.
1844   */
1845  public void setDatabasePlatform(DatabasePlatform databasePlatform) {
1846    this.databasePlatform = databasePlatform;
1847  }
1848
1849  /**
1850   * Return the preferred DB platform IdType.
1851   */
1852  public IdType getIdType() {
1853    return platformConfig.getIdType();
1854  }
1855
1856  /**
1857   * Set the preferred DB platform IdType.
1858   */
1859  public void setIdType(IdType idType) {
1860    this.platformConfig.setIdType(idType);
1861  }
1862
1863  /**
1864   * Return the EncryptKeyManager.
1865   */
1866  public EncryptKeyManager getEncryptKeyManager() {
1867    return encryptKeyManager;
1868  }
1869
1870  /**
1871   * Set the EncryptKeyManager.
1872   * <p>
1873   * This is required when you want to use encrypted properties.
1874   * <p>
1875   * You can also set this in ebean.proprerties:
1876   * <p>
1877   * <pre>{@code
1878   * # set via ebean.properties
1879   * ebean.encryptKeyManager=org.avaje.tests.basic.encrypt.BasicEncyptKeyManager
1880   * }</pre>
1881   */
1882  public void setEncryptKeyManager(EncryptKeyManager encryptKeyManager) {
1883    this.encryptKeyManager = encryptKeyManager;
1884  }
1885
1886  /**
1887   * Return the EncryptDeployManager.
1888   * <p>
1889   * This is optionally used to programmatically define which columns are
1890   * encrypted instead of using the {@link Encrypted} Annotation.
1891   */
1892  public EncryptDeployManager getEncryptDeployManager() {
1893    return encryptDeployManager;
1894  }
1895
1896  /**
1897   * Set the EncryptDeployManager.
1898   * <p>
1899   * This is optionally used to programmatically define which columns are
1900   * encrypted instead of using the {@link Encrypted} Annotation.
1901   */
1902  public void setEncryptDeployManager(EncryptDeployManager encryptDeployManager) {
1903    this.encryptDeployManager = encryptDeployManager;
1904  }
1905
1906  /**
1907   * Return the Encryptor used to encrypt data on the java client side (as
1908   * opposed to DB encryption functions).
1909   */
1910  public Encryptor getEncryptor() {
1911    return encryptor;
1912  }
1913
1914  /**
1915   * Set the Encryptor used to encrypt data on the java client side (as opposed
1916   * to DB encryption functions).
1917   * <p>
1918   * Ebean has a default implementation that it will use if you do not set your
1919   * own Encryptor implementation.
1920   */
1921  public void setEncryptor(Encryptor encryptor) {
1922    this.encryptor = encryptor;
1923  }
1924
1925  /**
1926   * Return true if the Database instance should be created in offline mode.
1927   */
1928  public boolean isDbOffline() {
1929    return dbOffline;
1930  }
1931
1932  /**
1933   * Set to true if the Database instance should be created in offline mode.
1934   * <p>
1935   * Typically used to create an Database instance for DDL Migration generation
1936   * without requiring a real DataSource / Database to connect to.
1937   */
1938  public void setDbOffline(boolean dbOffline) {
1939    this.dbOffline = dbOffline;
1940  }
1941
1942  /**
1943   * Return the DbEncrypt used to encrypt and decrypt properties.
1944   * <p>
1945   * Note that if this is not set then the DbPlatform may already have a
1946   * DbEncrypt set and that will be used.
1947   */
1948  public DbEncrypt getDbEncrypt() {
1949    return dbEncrypt;
1950  }
1951
1952  /**
1953   * Set the DbEncrypt used to encrypt and decrypt properties.
1954   * <p>
1955   * Note that if this is not set then the DbPlatform may already have a
1956   * DbEncrypt set (H2, MySql, Postgres and Oracle platforms have a DbEncrypt)
1957   */
1958  public void setDbEncrypt(DbEncrypt dbEncrypt) {
1959    this.dbEncrypt = dbEncrypt;
1960  }
1961
1962  /**
1963   * Return the configuration for DB types (such as UUID and custom mappings).
1964   */
1965  public PlatformConfig getPlatformConfig() {
1966    return platformConfig;
1967  }
1968
1969  /**
1970   * Set the configuration for DB platform (such as UUID and custom mappings).
1971   */
1972  public void setPlatformConfig(PlatformConfig platformConfig) {
1973    this.platformConfig = platformConfig;
1974  }
1975
1976  /**
1977   * Set the DB type used to store UUID.
1978   */
1979  public void setDbUuid(PlatformConfig.DbUuid dbUuid) {
1980    this.platformConfig.setDbUuid(dbUuid);
1981  }
1982
1983  /**
1984   * Returns the UUID version mode.
1985   */
1986  public UuidVersion getUuidVersion() {
1987    return uuidVersion;
1988  }
1989
1990  /**
1991   * Sets the UUID version mode.
1992   */
1993  public void setUuidVersion(UuidVersion uuidVersion) {
1994    this.uuidVersion = uuidVersion;
1995  }
1996
1997  /**
1998   * Return the UUID state file.
1999   */
2000  public String getUuidStateFile() {
2001    if (uuidStateFile == null || uuidStateFile.isEmpty()) {
2002      // by default, add servername...
2003      uuidStateFile = name + "-uuid.state";
2004      // and store it in the user's home directory
2005      String homeDir = System.getProperty("user.home");
2006      if (homeDir != null && homeDir.isEmpty()) {
2007        uuidStateFile = homeDir + "/.ebean/" + uuidStateFile;
2008      }
2009    }
2010    return uuidStateFile;
2011  }
2012
2013  /**
2014   * Set the UUID state file.
2015   */
2016  public void setUuidStateFile(String uuidStateFile) {
2017    this.uuidStateFile = uuidStateFile;
2018  }
2019
2020  /**
2021   * Return true if LocalTime should be persisted with nanos precision.
2022   */
2023  public boolean isLocalTimeWithNanos() {
2024    return localTimeWithNanos;
2025  }
2026
2027  /**
2028   * Set to true if LocalTime should be persisted with nanos precision.
2029   * <p>
2030   * Otherwise it is persisted using java.sql.Time which is seconds precision.
2031   */
2032  public void setLocalTimeWithNanos(boolean localTimeWithNanos) {
2033    this.localTimeWithNanos = localTimeWithNanos;
2034  }
2035
2036  /**
2037   * Return true if Duration should be persisted with nanos precision (SQL DECIMAL).
2038   * <p>
2039   * Otherwise it is persisted with second precision (SQL INTEGER).
2040   */
2041  public boolean isDurationWithNanos() {
2042    return durationWithNanos;
2043  }
2044
2045  /**
2046   * Set to true if Duration should be persisted with nanos precision (SQL DECIMAL).
2047   * <p>
2048   * Otherwise it is persisted with second precision (SQL INTEGER).
2049   */
2050  public void setDurationWithNanos(boolean durationWithNanos) {
2051    this.durationWithNanos = durationWithNanos;
2052  }
2053
2054  /**
2055   * Set to true to run DB migrations on server start.
2056   * <p>
2057   * This is the same as config.getMigrationConfig().setRunMigration(). We have added this method here
2058   * as it is often the only thing we need to configure for migrations.
2059   */
2060  public void setRunMigration(boolean runMigration) {
2061    this.runMigration = runMigration;
2062  }
2063
2064  /**
2065   * Return true if the DB migration should run on server start.
2066   */
2067  public boolean isRunMigration() {
2068    final String run = System.getProperty("ebean.migration.run");
2069    return (run != null) ? Boolean.parseBoolean(run) : runMigration;
2070  }
2071
2072  /**
2073   * Set to true to generate the "create all" DDL on startup.
2074   * <p>
2075   * Typically we want this on when we are running tests locally (and often using H2)
2076   * and we want to create the full DB schema from scratch to run tests.
2077   */
2078  public void setDdlGenerate(boolean ddlGenerate) {
2079    this.ddlGenerate = ddlGenerate;
2080  }
2081
2082  /**
2083   * Set to true to run the generated "create all DDL" on startup.
2084   * <p>
2085   * Typically we want this on when we are running tests locally (and often using H2)
2086   * and we want to create the full DB schema from scratch to run tests.
2087   */
2088  public void setDdlRun(boolean ddlRun) {
2089    this.ddlRun = ddlRun;
2090  }
2091
2092  /**
2093   * Set to false if you not want to run the extra-ddl.xml scripts. (default = true)
2094   * <p>
2095   * Typically we want this on when we are running tests.
2096   */
2097  public void setDdlExtra(boolean ddlExtra) {
2098    this.ddlExtra = ddlExtra;
2099  }
2100
2101
2102  /**
2103   * Return true if the "drop all ddl" should be skipped.
2104   * <p>
2105   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
2106   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
2107   */
2108  public boolean isDdlCreateOnly() {
2109    return ddlCreateOnly;
2110  }
2111
2112  /**
2113   * Set to true if the "drop all ddl" should be skipped.
2114   * <p>
2115   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
2116   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
2117   */
2118  public void setDdlCreateOnly(boolean ddlCreateOnly) {
2119    this.ddlCreateOnly = ddlCreateOnly;
2120  }
2121
2122  /**
2123   * Return SQL script to execute after the "create all" DDL has been run.
2124   * <p>
2125   * Typically this is a sql script that inserts test seed data when running tests.
2126   * Place a sql script in src/test/resources that inserts test seed data.
2127   */
2128  public String getDdlSeedSql() {
2129    return ddlSeedSql;
2130  }
2131
2132  /**
2133   * Set a SQL script to execute after the "create all" DDL has been run.
2134   * <p>
2135   * Typically this is a sql script that inserts test seed data when running tests.
2136   * Place a sql script in src/test/resources that inserts test seed data.
2137   */
2138  public void setDdlSeedSql(String ddlSeedSql) {
2139    this.ddlSeedSql = ddlSeedSql;
2140  }
2141
2142  /**
2143   * Return a SQL script to execute before the "create all" DDL has been run.
2144   */
2145  public String getDdlInitSql() {
2146    return ddlInitSql;
2147  }
2148
2149  /**
2150   * Set a SQL script to execute before the "create all" DDL has been run.
2151   */
2152  public void setDdlInitSql(String ddlInitSql) {
2153    this.ddlInitSql = ddlInitSql;
2154  }
2155
2156  /**
2157   * Return true if the DDL should be generated.
2158   */
2159  public boolean isDdlGenerate() {
2160    return ddlGenerate;
2161  }
2162
2163  /**
2164   * Return true if the DDL should be run.
2165   */
2166  public boolean isDdlRun() {
2167    return ddlRun;
2168  }
2169
2170  /**
2171   * Return true, if extra-ddl.xml should be executed.
2172   */
2173  public boolean isDdlExtra() {
2174    return ddlExtra;
2175  }
2176
2177  /**
2178   * Set the header to use with DDL generation.
2179   */
2180  public void setDdlHeader(String ddlHeader) {
2181    this.ddlHeader = ddlHeader;
2182  }
2183
2184  /**
2185   * Return the header to use with DDL generation.
2186   */
2187  public String getDdlHeader() {
2188    if (ddlHeader != null && !ddlHeader.isEmpty()) {
2189      String header = ddlHeader.replace("${version}", EbeanVersion.getVersion());
2190      header = header.replace("${timestamp}", ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT));
2191      return header;
2192    }
2193    return ddlHeader;
2194  }
2195
2196  /**
2197   * Return true if strict mode is used which includes a check that non-null columns have a default value.
2198   */
2199  public boolean isDdlStrictMode() {
2200    return ddlStrictMode;
2201  }
2202
2203  /**
2204   * Set to false to turn off strict mode allowing non-null columns to not have a default value.
2205   */
2206  public void setDdlStrictMode(boolean ddlStrictMode) {
2207    this.ddlStrictMode = ddlStrictMode;
2208  }
2209
2210  /**
2211   * Return a comma and equals delimited placeholders that are substituted in DDL scripts.
2212   */
2213  public String getDdlPlaceholders() {
2214    return ddlPlaceholders;
2215  }
2216
2217  /**
2218   * Set a comma and equals delimited placeholders that are substituted in DDL scripts.
2219   */
2220  public void setDdlPlaceholders(String ddlPlaceholders) {
2221    this.ddlPlaceholders = ddlPlaceholders;
2222  }
2223
2224  /**
2225   * Return a map of placeholder values that are substituted in DDL scripts.
2226   */
2227  public Map<String, String> getDdlPlaceholderMap() {
2228    return ddlPlaceholderMap;
2229  }
2230
2231  /**
2232   * Set a map of placeholder values that are substituted in DDL scripts.
2233   */
2234  public void setDdlPlaceholderMap(Map<String, String> ddlPlaceholderMap) {
2235    this.ddlPlaceholderMap = ddlPlaceholderMap;
2236  }
2237
2238  /**
2239   * Return true if the class path search should be disabled.
2240   */
2241  public boolean isDisableClasspathSearch() {
2242    return disableClasspathSearch;
2243  }
2244
2245  /**
2246   * Set to true to disable the class path search even for the case where no entity bean classes
2247   * have been registered. This can be used to start an Database instance just to use the
2248   * SQL functions such as SqlQuery, SqlUpdate etc.
2249   */
2250  public void setDisableClasspathSearch(boolean disableClasspathSearch) {
2251    this.disableClasspathSearch = disableClasspathSearch;
2252  }
2253
2254  /**
2255   * Return the mode to use for Joda LocalTime support 'normal' or 'utc'.
2256   */
2257  public String getJodaLocalTimeMode() {
2258    return jodaLocalTimeMode;
2259  }
2260
2261  /**
2262   * Set the mode to use for Joda LocalTime support 'normal' or 'utc'.
2263   */
2264  public void setJodaLocalTimeMode(String jodaLocalTimeMode) {
2265    this.jodaLocalTimeMode = jodaLocalTimeMode;
2266  }
2267
2268  /**
2269   * Programmatically add classes (typically entities) that this server should
2270   * use.
2271   * <p>
2272   * The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
2273   * BeanFinder or BeanPersistController.
2274   * <p>
2275   * If no classes are specified then the classes are found automatically via
2276   * searching the class path.
2277   * <p>
2278   * Alternatively the classes can be added via {@link #setClasses(List)}.
2279   *
2280   * @param cls the entity type (or other type) that should be registered by this
2281   *            database.
2282   */
2283  public void addClass(Class<?> cls) {
2284    classes.add(cls);
2285  }
2286
2287  /**
2288   * Register all the classes (typically entity classes).
2289   */
2290  public void addAll(List<Class<?>> classList) {
2291    if (classList != null && !classList.isEmpty()) {
2292      classes.addAll(classList);
2293    }
2294  }
2295
2296  /**
2297   * Add a package to search for entities via class path search.
2298   * <p>
2299   * This is only used if classes have not been explicitly specified.
2300   */
2301  public void addPackage(String packageName) {
2302    packages.add(packageName);
2303  }
2304
2305  /**
2306   * Return packages to search for entities via class path search.
2307   * <p>
2308   * This is only used if classes have not been explicitly specified.
2309   */
2310  public List<String> getPackages() {
2311    return packages;
2312  }
2313
2314  /**
2315   * Set packages to search for entities via class path search.
2316   * <p>
2317   * This is only used if classes have not been explicitly specified.
2318   */
2319  public void setPackages(List<String> packages) {
2320    this.packages = packages;
2321  }
2322
2323  /**
2324   * Set the list of classes (entities, listeners, scalarTypes etc) that should
2325   * be used for this database.
2326   * <p>
2327   * If no classes are specified then the classes are found automatically via
2328   * searching the class path.
2329   * <p>
2330   * Alternatively the classes can contain added via {@link #addClass(Class)}.
2331   */
2332  public void setClasses(List<Class<?>> classes) {
2333    this.classes = classes;
2334  }
2335
2336  /**
2337   * Return the classes registered for this database. Typically this includes
2338   * entities and perhaps listeners.
2339   */
2340  public List<Class<?>> getClasses() {
2341    return classes;
2342  }
2343
2344  /**
2345   * Return true if L2 bean cache should be skipped once writes have occurred on a transaction.
2346   * <p>
2347   * This defaults to true and means that for "find by id" and "find by natural key"
2348   * queries that normally hit L2 bean cache automatically will not do so after a write/persist
2349   * on the transaction.
2350   * <p>
2351   * <pre>{@code
2352   *
2353   *   // assume Customer has L2 bean caching enabled ...
2354   *
2355   *   try (Transaction transaction = DB.beginTransaction()) {
2356   *
2357   *     // this uses L2 bean cache as the transaction
2358   *     // ... is considered "query only" at this point
2359   *     Customer.find.byId(42);
2360   *
2361   *     // transaction no longer "query only" once
2362   *     // ... a bean has been saved etc
2363   *     DB.save(someBean);
2364   *
2365   *     // will NOT use L2 bean cache as the transaction
2366   *     // ... is no longer considered "query only"
2367   *     Customer.find.byId(55);
2368   *
2369   *
2370   *
2371   *     // explicit control - please use L2 bean cache
2372   *
2373   *     transaction.setSkipCache(false);
2374   *     Customer.find.byId(77); // hit the l2 bean cache
2375   *
2376   *
2377   *     // explicit control - please don't use L2 bean cache
2378   *
2379   *     transaction.setSkipCache(true);
2380   *     Customer.find.byId(99); // skips l2 bean cache
2381   *
2382   *   }
2383   *
2384   * }</pre>
2385   *
2386   * @see Transaction#setSkipCache(boolean)
2387   */
2388  public boolean isSkipCacheAfterWrite() {
2389    return skipCacheAfterWrite;
2390  }
2391
2392  /**
2393   * Set to false when we still want to hit the cache after a write has occurred on a transaction.
2394   */
2395  public void setSkipCacheAfterWrite(boolean skipCacheAfterWrite) {
2396    this.skipCacheAfterWrite = skipCacheAfterWrite;
2397  }
2398
2399  /**
2400   * Returns true if updates in JDBC batch default to include all properties by default.
2401   */
2402  public boolean isUpdateAllPropertiesInBatch() {
2403    return updateAllPropertiesInBatch;
2404  }
2405
2406  /**
2407   * Set to false if by default updates in JDBC batch should not include all properties.
2408   * <p>
2409   * This mode can be explicitly set per transaction.
2410   *
2411   * @see Transaction#setUpdateAllLoadedProperties(boolean)
2412   */
2413  public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
2414    this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
2415  }
2416
2417  /**
2418   * Returns the resource directory.
2419   */
2420  public String getResourceDirectory() {
2421    return resourceDirectory;
2422  }
2423
2424  /**
2425   * Sets the resource directory.
2426   */
2427  public void setResourceDirectory(String resourceDirectory) {
2428    this.resourceDirectory = resourceDirectory;
2429  }
2430
2431  /**
2432   * Add a custom type mapping.
2433   * <p>
2434   * <pre>{@code
2435   *
2436   *   // set the default mapping for BigDecimal.class/decimal
2437   *   config.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
2438   *
2439   *   // set the default mapping for String.class/varchar but only for Postgres
2440   *   config.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES);
2441   *
2442   * }</pre>
2443   *
2444   * @param type             The DB type this mapping should apply to
2445   * @param columnDefinition The column definition that should be used
2446   * @param platform         Optionally specify the platform this mapping should apply to.
2447   */
2448  public void addCustomMapping(DbType type, String columnDefinition, Platform platform) {
2449    platformConfig.addCustomMapping(type, columnDefinition, platform);
2450  }
2451
2452  /**
2453   * Add a custom type mapping that applies to all platforms.
2454   * <p>
2455   * <pre>{@code
2456   *
2457   *   // set the default mapping for BigDecimal/decimal
2458   *   config.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
2459   *
2460   *   // set the default mapping for String/varchar
2461   *   config.addCustomMapping(DbType.VARCHAR, "text");
2462   *
2463   * }</pre>
2464   *
2465   * @param type             The DB type this mapping should apply to
2466   * @param columnDefinition The column definition that should be used
2467   */
2468  public void addCustomMapping(DbType type, String columnDefinition) {
2469    platformConfig.addCustomMapping(type, columnDefinition);
2470  }
2471
2472  /**
2473   * Register a BeanQueryAdapter instance.
2474   * <p>
2475   * Note alternatively you can use {@link #setQueryAdapters(List)} to set all
2476   * the BeanQueryAdapter instances.
2477   */
2478  public void add(BeanQueryAdapter beanQueryAdapter) {
2479    queryAdapters.add(beanQueryAdapter);
2480  }
2481
2482  /**
2483   * Return the BeanQueryAdapter instances.
2484   */
2485  public List<BeanQueryAdapter> getQueryAdapters() {
2486    return queryAdapters;
2487  }
2488
2489  /**
2490   * Register all the BeanQueryAdapter instances.
2491   * <p>
2492   * Note alternatively you can use {@link #add(BeanQueryAdapter)} to add
2493   * BeanQueryAdapter instances one at a time.
2494   */
2495  public void setQueryAdapters(List<BeanQueryAdapter> queryAdapters) {
2496    this.queryAdapters = queryAdapters;
2497  }
2498
2499  /**
2500   * Return the custom IdGenerator instances.
2501   */
2502  public List<IdGenerator> getIdGenerators() {
2503    return idGenerators;
2504  }
2505
2506  /**
2507   * Set the custom IdGenerator instances.
2508   */
2509  public void setIdGenerators(List<IdGenerator> idGenerators) {
2510    this.idGenerators = idGenerators;
2511  }
2512
2513  /**
2514   * Register a customer IdGenerator instance.
2515   */
2516  public void add(IdGenerator idGenerator) {
2517    idGenerators.add(idGenerator);
2518  }
2519
2520  /**
2521   * Register a BeanPersistController instance.
2522   * <p>
2523   * Note alternatively you can use {@link #setPersistControllers(List)} to set
2524   * all the BeanPersistController instances.
2525   */
2526  public void add(BeanPersistController beanPersistController) {
2527    persistControllers.add(beanPersistController);
2528  }
2529
2530  /**
2531   * Register a BeanPostLoad instance.
2532   * <p>
2533   * Note alternatively you can use {@link #setPostLoaders(List)} to set
2534   * all the BeanPostLoad instances.
2535   */
2536  public void add(BeanPostLoad postLoad) {
2537    postLoaders.add(postLoad);
2538  }
2539
2540  /**
2541   * Register a BeanPostConstructListener instance.
2542   * <p>
2543   * Note alternatively you can use {@link #setPostConstructListeners(List)} to set
2544   * all the BeanPostConstructListener instances.
2545   */
2546  public void add(BeanPostConstructListener listener) {
2547    postConstructListeners.add(listener);
2548  }
2549
2550  /**
2551   * Return the list of BeanFindController instances.
2552   */
2553  public List<BeanFindController> getFindControllers() {
2554    return findControllers;
2555  }
2556
2557  /**
2558   * Set the list of BeanFindController instances.
2559   */
2560  public void setFindControllers(List<BeanFindController> findControllers) {
2561    this.findControllers = findControllers;
2562  }
2563
2564  /**
2565   * Return the list of BeanPostLoader instances.
2566   */
2567  public List<BeanPostLoad> getPostLoaders() {
2568    return postLoaders;
2569  }
2570
2571  /**
2572   * Set the list of BeanPostLoader instances.
2573   */
2574  public void setPostLoaders(List<BeanPostLoad> postLoaders) {
2575    this.postLoaders = postLoaders;
2576  }
2577
2578  /**
2579   * Return the list of BeanPostLoader instances.
2580   */
2581  public List<BeanPostConstructListener> getPostConstructListeners() {
2582    return postConstructListeners;
2583  }
2584
2585  /**
2586   * Set the list of BeanPostLoader instances.
2587   */
2588  public void setPostConstructListeners(List<BeanPostConstructListener> listeners) {
2589    this.postConstructListeners = listeners;
2590  }
2591
2592  /**
2593   * Return the BeanPersistController instances.
2594   */
2595  public List<BeanPersistController> getPersistControllers() {
2596    return persistControllers;
2597  }
2598
2599  /**
2600   * Register all the BeanPersistController instances.
2601   * <p>
2602   * Note alternatively you can use {@link #add(BeanPersistController)} to add
2603   * BeanPersistController instances one at a time.
2604   */
2605  public void setPersistControllers(List<BeanPersistController> persistControllers) {
2606    this.persistControllers = persistControllers;
2607  }
2608
2609  /**
2610   * Register a BeanPersistListener instance.
2611   * <p>
2612   * Note alternatively you can use {@link #setPersistListeners(List)} to set
2613   * all the BeanPersistListener instances.
2614   */
2615  public void add(BeanPersistListener beanPersistListener) {
2616    persistListeners.add(beanPersistListener);
2617  }
2618
2619  /**
2620   * Return the BeanPersistListener instances.
2621   */
2622  public List<BeanPersistListener> getPersistListeners() {
2623    return persistListeners;
2624  }
2625
2626  /**
2627   * Add a BulkTableEventListener
2628   */
2629  public void add(BulkTableEventListener bulkTableEventListener) {
2630    bulkTableEventListeners.add(bulkTableEventListener);
2631  }
2632
2633  /**
2634   * Return the list of BulkTableEventListener instances.
2635   */
2636  public List<BulkTableEventListener> getBulkTableEventListeners() {
2637    return bulkTableEventListeners;
2638  }
2639
2640  /**
2641   * Add a ServerConfigStartup.
2642   */
2643  public void addServerConfigStartup(ServerConfigStartup configStartupListener) {
2644    configStartupListeners.add(configStartupListener);
2645  }
2646
2647  /**
2648   * Return the list of ServerConfigStartup instances.
2649   */
2650  public List<ServerConfigStartup> getServerConfigStartupListeners() {
2651    return configStartupListeners;
2652  }
2653
2654  /**
2655   * Register all the BeanPersistListener instances.
2656   * <p>
2657   * Note alternatively you can use {@link #add(BeanPersistListener)} to add
2658   * BeanPersistListener instances one at a time.
2659   */
2660  public void setPersistListeners(List<BeanPersistListener> persistListeners) {
2661    this.persistListeners = persistListeners;
2662  }
2663
2664  /**
2665   * Return the default PersistenceContextScope to be used if one is not explicitly set on a query.
2666   * <p/>
2667   * The PersistenceContextScope can specified on each query via {@link io.ebean
2668   * .Query#setPersistenceContextScope(io.ebean.PersistenceContextScope)}. If it
2669   * is not set on the query this default scope is used.
2670   *
2671   * @see Query#setPersistenceContextScope(PersistenceContextScope)
2672   */
2673  public PersistenceContextScope getPersistenceContextScope() {
2674    // if somehow null return TRANSACTION scope
2675    return persistenceContextScope == null ? PersistenceContextScope.TRANSACTION : persistenceContextScope;
2676  }
2677
2678  /**
2679   * Set the PersistenceContext scope to be used if one is not explicitly set on a query.
2680   * <p/>
2681   * This defaults to {@link PersistenceContextScope#TRANSACTION}.
2682   * <p/>
2683   * The PersistenceContextScope can specified on each query via {@link io.ebean
2684   * .Query#setPersistenceContextScope(io.ebean.PersistenceContextScope)}. If it
2685   * is not set on the query this scope is used.
2686   *
2687   * @see Query#setPersistenceContextScope(PersistenceContextScope)
2688   */
2689  public void setPersistenceContextScope(PersistenceContextScope persistenceContextScope) {
2690    this.persistenceContextScope = persistenceContextScope;
2691  }
2692
2693  /**
2694   * Return the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2695   * create new instances of plugins given a className.
2696   */
2697  public ClassLoadConfig getClassLoadConfig() {
2698    return classLoadConfig;
2699  }
2700
2701  /**
2702   * Set the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2703   * create new instances of plugins given a className.
2704   */
2705  public void setClassLoadConfig(ClassLoadConfig classLoadConfig) {
2706    this.classLoadConfig = classLoadConfig;
2707  }
2708
2709
2710
2711  /**
2712   * Load settings from application.properties, application.yaml and other sources.
2713   * <p>
2714   * Uses <code>avaje-config</code> to load configuration properties.  Goto https://avaje.io/config
2715   * for detail on how and where properties are loaded from.
2716   */
2717  public void loadFromProperties() {
2718    this.properties = Config.asProperties();
2719    configureFromProperties();
2720  }
2721
2722  /**
2723   * Load the settings from the given properties
2724   */
2725  public void loadFromProperties(Properties properties) {
2726    // keep the properties used for configuration so that these are available for plugins
2727    this.properties = Config.asConfiguration().eval(properties);
2728    configureFromProperties();
2729  }
2730
2731  /**
2732   * Load the settings from the given properties
2733   */
2734  private void configureFromProperties() {
2735    List<AutoConfigure> autoConfigures = autoConfiguration();
2736    loadSettings(new PropertiesWrapper("ebean", name, properties, classLoadConfig));
2737    for (AutoConfigure autoConfigure : autoConfigures) {
2738      autoConfigure.postConfigure(this);
2739    }
2740  }
2741
2742  /**
2743   * Use a 'plugin' to provide automatic configuration. Intended for automatic testing
2744   * configuration with Docker containers via ebean-test-config.
2745   */
2746  private List<AutoConfigure> autoConfiguration() {
2747    List<AutoConfigure> list = new ArrayList<>();
2748    for (AutoConfigure autoConfigure : ServiceLoader.load(AutoConfigure.class)) {
2749      autoConfigure.preConfigure(this);
2750      list.add(autoConfigure);
2751    }
2752    return list;
2753  }
2754
2755  /**
2756   * Return the properties that we used for configuration and were set via a call to loadFromProperties().
2757   */
2758  public Properties getProperties() {
2759    return properties;
2760  }
2761
2762  /**
2763   * loads the data source settings to preserve existing behaviour. IMHO, if someone has set the datasource config already,
2764   * they don't want the settings to be reloaded and reset. This allows a descending class to override this behaviour and prevent it
2765   * from happening.
2766   *
2767   * @param p - The defined property source passed to load settings
2768   */
2769  protected void loadDataSourceSettings(PropertiesWrapper p) {
2770    dataSourceConfig.loadSettings(p.properties, name);
2771    readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
2772  }
2773
2774  /**
2775   * This is broken out to allow overridden behaviour.
2776   */
2777  protected void loadDocStoreSettings(PropertiesWrapper p) {
2778    docStoreConfig.loadSettings(p);
2779  }
2780
2781  /**
2782   * This is broken out to allow overridden behaviour.
2783   */
2784  protected void loadAutoTuneSettings(PropertiesWrapper p) {
2785    autoTuneConfig.loadSettings(p);
2786  }
2787
2788  /**
2789   * Load the configuration settings from the properties file.
2790   */
2791  protected void loadSettings(PropertiesWrapper p) {
2792    dbSchema = p.get("dbSchema", dbSchema);
2793    profilingConfig.loadSettings(p, name);
2794    platformConfig.loadSettings(p);
2795    if (platformConfig.isAllQuotedIdentifiers()) {
2796      adjustNamingConventionForAllQuoted();
2797    }
2798    namingConvention = createNamingConvention(p, namingConvention);
2799    if (namingConvention != null) {
2800      namingConvention.loadFromProperties(p);
2801    }
2802    if (autoTuneConfig == null) {
2803      autoTuneConfig = new AutoTuneConfig();
2804    }
2805    loadAutoTuneSettings(p);
2806
2807    if (dataSourceConfig == null) {
2808      dataSourceConfig = new DataSourceConfig();
2809    }
2810    loadDataSourceSettings(p);
2811
2812    if (docStoreConfig == null) {
2813      docStoreConfig = new DocStoreConfig();
2814    }
2815    loadDocStoreSettings(p);
2816
2817    defaultServer = p.getBoolean("defaultServer", defaultServer);
2818    autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
2819    loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
2820    maxCallStack = p.getInt("maxCallStack", maxCallStack);
2821    dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
2822    dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
2823    queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
2824    slowQueryMillis = p.getLong("slowQueryMillis", slowQueryMillis);
2825    queryPlanEnable = p.getBoolean("queryPlan.enable", queryPlanEnable);
2826    queryPlanThresholdMicros = p.getLong("queryPlan.thresholdMicros", queryPlanThresholdMicros);
2827    queryPlanCapture = p.getBoolean("queryPlan.capture", queryPlanCapture);
2828    queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
2829    queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
2830    queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
2831    docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
2832    disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
2833    localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
2834    enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
2835    notifyL2CacheInForeground = p.getBoolean("notifyL2CacheInForeground", notifyL2CacheInForeground);
2836    useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
2837    useValidationNotNull = p.getBoolean("useValidationNotNull", useValidationNotNull);
2838    autoReadOnlyDataSource = p.getBoolean("autoReadOnlyDataSource", autoReadOnlyDataSource);
2839    idGeneratorAutomatic = p.getBoolean("idGeneratorAutomatic", idGeneratorAutomatic);
2840
2841    backgroundExecutorSchedulePoolSize = p.getInt("backgroundExecutorSchedulePoolSize", backgroundExecutorSchedulePoolSize);
2842    backgroundExecutorShutdownSecs = p.getInt("backgroundExecutorShutdownSecs", backgroundExecutorShutdownSecs);
2843    disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
2844    currentUserProvider = p.createInstance(CurrentUserProvider.class, "currentUserProvider", currentUserProvider);
2845    databasePlatform = p.createInstance(DatabasePlatform.class, "databasePlatform", databasePlatform);
2846    encryptKeyManager = p.createInstance(EncryptKeyManager.class, "encryptKeyManager", encryptKeyManager);
2847    encryptDeployManager = p.createInstance(EncryptDeployManager.class, "encryptDeployManager", encryptDeployManager);
2848    encryptor = p.createInstance(Encryptor.class, "encryptor", encryptor);
2849    dbEncrypt = p.createInstance(DbEncrypt.class, "dbEncrypt", dbEncrypt);
2850    dbOffline = p.getBoolean("dbOffline", dbOffline);
2851    serverCachePlugin = p.createInstance(ServerCachePlugin.class, "serverCachePlugin", serverCachePlugin);
2852
2853    String packagesProp = p.get("search.packages", p.get("packages", null));
2854    packages = getSearchList(packagesProp, packages);
2855
2856    skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
2857    updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
2858
2859    if (p.get("batch.mode") != null || p.get("persistBatching") != null) {
2860      throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
2861    }
2862
2863    persistBatch = p.getEnum(PersistBatch.class, "persistBatch", persistBatch);
2864    persistBatchOnCascade = p.getEnum(PersistBatch.class, "persistBatchOnCascade", persistBatchOnCascade);
2865
2866    int batchSize = p.getInt("batch.size", persistBatchSize);
2867    persistBatchSize = p.getInt("persistBatchSize", batchSize);
2868
2869    persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
2870
2871    changeLogAsync = p.getBoolean("changeLogAsync", changeLogAsync);
2872    changeLogIncludeInserts = p.getBoolean("changeLogIncludeInserts", changeLogIncludeInserts);
2873    expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
2874    expressionNativeIlike = p.getBoolean("expressionNativeIlike", expressionNativeIlike);
2875
2876    dataTimeZone = p.get("dataTimeZone", dataTimeZone);
2877    asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
2878    asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
2879    historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
2880    dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
2881    jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
2882    jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
2883    databasePlatformName = p.get("databasePlatformName", databasePlatformName);
2884    defaultOrderById = p.getBoolean("defaultOrderById", defaultOrderById);
2885
2886    uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
2887    uuidStateFile = p.get("uuidStateFile", uuidStateFile);
2888
2889    localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
2890    jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
2891
2892    defaultEnumType = p.getEnum(EnumType.class, "defaultEnumType", defaultEnumType);
2893    disableLazyLoading = p.getBoolean("disableLazyLoading", disableLazyLoading);
2894    lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
2895    queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
2896
2897    jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
2898    jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime);
2899    jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate);
2900    jsonMutationDetection = p.getEnum(MutationDetection.class, "jsonMutationDetection", jsonMutationDetection);
2901
2902    skipDataSourceCheck = p.getBoolean("skipDataSourceCheck", skipDataSourceCheck);
2903    runMigration = p.getBoolean("migration.run", runMigration);
2904    ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
2905    ddlRun = p.getBoolean("ddl.run", ddlRun);
2906    ddlExtra = p.getBoolean("ddl.extra", ddlExtra);
2907    ddlCreateOnly = p.getBoolean("ddl.createOnly", ddlCreateOnly);
2908    ddlInitSql = p.get("ddl.initSql", ddlInitSql);
2909    ddlSeedSql = p.get("ddl.seedSql", ddlSeedSql);
2910    ddlStrictMode = p.getBoolean("ddl.strictMode", ddlStrictMode);
2911    ddlPlaceholders = p.get("ddl.placeholders", ddlPlaceholders);
2912    ddlHeader = p.get("ddl.header", ddlHeader);
2913
2914    // read tenant-configuration from config:
2915    // tenant.mode = NONE | DB | SCHEMA | CATALOG | PARTITION
2916    String mode = p.get("tenant.mode");
2917    if (mode != null) {
2918      for (TenantMode value : TenantMode.values()) {
2919        if (value.name().equalsIgnoreCase(mode)) {
2920          tenantMode = value;
2921          break;
2922        }
2923      }
2924    }
2925
2926    currentTenantProvider = p.createInstance(CurrentTenantProvider.class, "tenant.currentTenantProvider", currentTenantProvider);
2927    tenantCatalogProvider = p.createInstance(TenantCatalogProvider.class, "tenant.catalogProvider", tenantCatalogProvider);
2928    tenantSchemaProvider = p.createInstance(TenantSchemaProvider.class, "tenant.schemaProvider", tenantSchemaProvider);
2929    tenantPartitionColumn = p.get("tenant.partitionColumn", tenantPartitionColumn);
2930    classes = getClasses(p);
2931
2932    String mappingsProp = p.get("mappingLocations", null);
2933    mappingLocations = getSearchList(mappingsProp, mappingLocations);
2934  }
2935
2936  private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
2937    NamingConvention nc = properties.createInstance(NamingConvention.class, "namingConvention", null);
2938    return (nc != null) ? nc : namingConvention;
2939  }
2940
2941  /**
2942   * Build the list of classes from the comma delimited string.
2943   *
2944   * @param properties the properties
2945   * @return the classes
2946   */
2947  private List<Class<?>> getClasses(PropertiesWrapper properties) {
2948    String classNames = properties.get("classes", null);
2949    if (classNames == null) {
2950      return classes;
2951    }
2952
2953    List<Class<?>> classList = new ArrayList<>();
2954    String[] split = StringHelper.splitNames(classNames);
2955    for (String cn : split) {
2956      if (!"class".equalsIgnoreCase(cn)) {
2957        try {
2958          classList.add(Class.forName(cn));
2959        } catch (ClassNotFoundException e) {
2960          String msg = "Error registering class [" + cn + "] from [" + classNames + "]";
2961          throw new RuntimeException(msg, e);
2962        }
2963      }
2964    }
2965    return classList;
2966  }
2967
2968  private List<String> getSearchList(String searchNames, List<String> defaultValue) {
2969    if (searchNames != null) {
2970      String[] entries = StringHelper.splitNames(searchNames);
2971      List<String> hitList = new ArrayList<>(entries.length);
2972      Collections.addAll(hitList, entries);
2973      return hitList;
2974    } else {
2975      return defaultValue;
2976    }
2977  }
2978
2979  /**
2980   * Return the PersistBatch mode to use for 'batchOnCascade' taking into account if the database
2981   * platform supports getGeneratedKeys in batch mode.
2982   */
2983  public PersistBatch appliedPersistBatchOnCascade() {
2984    if (persistBatchOnCascade == PersistBatch.INHERIT) {
2985      // use the platform default (ALL except SQL Server which has NONE)
2986      return databasePlatform.getPersistBatchOnCascade();
2987    }
2988    return persistBatchOnCascade;
2989  }
2990
2991  /**
2992   * Return the Jackson ObjectMapper.
2993   * <p>
2994   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
2995   */
2996  public Object getObjectMapper() {
2997    return objectMapper;
2998  }
2999
3000  /**
3001   * Set the Jackson ObjectMapper.
3002   * <p>
3003   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
3004   */
3005  public void setObjectMapper(Object objectMapper) {
3006    this.objectMapper = objectMapper;
3007  }
3008
3009  /**
3010   * Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
3011   */
3012  public boolean isExpressionEqualsWithNullAsNoop() {
3013    return expressionEqualsWithNullAsNoop;
3014  }
3015
3016  /**
3017   * Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
3018   * <p>
3019   * Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
3020   * ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
3021   * which will add "1=1" into the SQL rather than "is null".
3022   */
3023  public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
3024    this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
3025  }
3026
3027  /**
3028   * Return true if native ILIKE expression should be used if supported by the database platform (e.g. Postgres).
3029   */
3030  public boolean isExpressionNativeIlike() {
3031    return expressionNativeIlike;
3032  }
3033
3034  /**
3035   * Set to true to use native ILIKE expression if supported by the database platform (e.g. Postgres).
3036   */
3037  public void setExpressionNativeIlike(boolean expressionNativeIlike) {
3038    this.expressionNativeIlike = expressionNativeIlike;
3039  }
3040
3041  /**
3042   * Return the enabled L2 cache regions.
3043   */
3044  public String getEnabledL2Regions() {
3045    return enabledL2Regions;
3046  }
3047
3048  /**
3049   * Set the enabled L2 cache regions (comma delimited).
3050   */
3051  public void setEnabledL2Regions(String enabledL2Regions) {
3052    this.enabledL2Regions = enabledL2Regions;
3053  }
3054
3055  /**
3056   * Return true if L2 cache is disabled.
3057   */
3058  public boolean isDisableL2Cache() {
3059    return disableL2Cache;
3060  }
3061
3062  /**
3063   * Set to true to disable L2 caching. Typically useful in performance testing.
3064   */
3065  public void setDisableL2Cache(boolean disableL2Cache) {
3066    this.disableL2Cache = disableL2Cache;
3067  }
3068
3069  /**
3070   * Return true to use local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
3071   */
3072  public boolean isLocalOnlyL2Cache() {
3073    return localOnlyL2Cache;
3074  }
3075
3076  /**
3077   * Force the use of local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
3078   */
3079  public void setLocalOnlyL2Cache(boolean localOnlyL2Cache) {
3080    this.localOnlyL2Cache = localOnlyL2Cache;
3081  }
3082
3083  /**
3084   * Returns if we use javax.validation.constraints.NotNull
3085   */
3086  public boolean isUseValidationNotNull() {
3087    return useValidationNotNull;
3088  }
3089
3090  /**
3091   * Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code> or
3092   * <code>&x64;jakarta.validation.contstraints.NotNull</code>
3093   * with respect to generating a <code>NOT NULL</code> column.
3094   * <p>
3095   * Normally when Ebean sees javax NotNull annotation it means that column is defined as NOT NULL.
3096   * Set this to <code>false</code> and the javax NotNull annotation is effectively ignored (and
3097   * we instead use Ebean's own NotNull annotation or JPA Column(nullable=false) annotation.
3098   */
3099  public void setUseValidationNotNull(boolean useValidationNotNull) {
3100    this.useValidationNotNull = useValidationNotNull;
3101  }
3102
3103  /**
3104   * Return true if L2 cache notification should run in the foreground.
3105   */
3106  public boolean isNotifyL2CacheInForeground() {
3107    return notifyL2CacheInForeground;
3108  }
3109
3110  /**
3111   * Set this to true to run L2 cache notification in the foreground.
3112   * <p>
3113   * In general we don't want to do that as when we use a distributed cache (like Ignite, Hazelcast etc)
3114   * we are making network calls and we prefer to do this in background and not impact the response time
3115   * of the executing transaction.
3116   */
3117  public void setNotifyL2CacheInForeground(boolean notifyL2CacheInForeground) {
3118    this.notifyL2CacheInForeground = notifyL2CacheInForeground;
3119  }
3120
3121  /**
3122   * Return the time to live for ebean's internal query plan.
3123   */
3124  public int getQueryPlanTTLSeconds() {
3125    return queryPlanTTLSeconds;
3126  }
3127
3128  /**
3129   * Set the time to live for ebean's internal query plan.
3130   * <p>
3131   * This is the plan that knows how to execute the query, read the result
3132   * and collects execution metrics. By default this is set to 5 mins.
3133   */
3134  public void setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
3135    this.queryPlanTTLSeconds = queryPlanTTLSeconds;
3136  }
3137
3138  /**
3139   * Create a new PlatformConfig based of the one held but with overridden properties by reading
3140   * properties with the given path and prefix.
3141   * <p>
3142   * Typically used in Db Migration generation for many platform targets that might have different
3143   * configuration for IdType, UUID, quoted identifiers etc.
3144   *
3145   * @param propertiesPath The properties path used for loading and setting properties
3146   * @param platformPrefix The prefix used for loading and setting properties
3147   * @return A copy of the PlatformConfig with overridden properties
3148   */
3149  public PlatformConfig newPlatformConfig(String propertiesPath, String platformPrefix) {
3150    if (properties == null) {
3151      properties = new Properties();
3152    }
3153    PropertiesWrapper p = new PropertiesWrapper(propertiesPath, platformPrefix, properties, classLoadConfig);
3154    PlatformConfig config = new PlatformConfig(platformConfig);
3155    config.loadSettings(p);
3156    return config;
3157  }
3158
3159  /**
3160   * Add a mapping location to search for xml mapping via class path search.
3161   */
3162  public void addMappingLocation(String mappingLocation) {
3163    if (mappingLocations == null) {
3164      mappingLocations = new ArrayList<>();
3165    }
3166    mappingLocations.add(mappingLocation);
3167  }
3168
3169  /**
3170   * Return mapping locations to search for xml mapping via class path search.
3171   */
3172  public List<String> getMappingLocations() {
3173    return mappingLocations;
3174  }
3175
3176  /**
3177   * Set mapping locations to search for xml mapping via class path search.
3178   * <p>
3179   * This is only used if classes have not been explicitly specified.
3180   */
3181  public void setMappingLocations(List<String> mappingLocations) {
3182    this.mappingLocations = mappingLocations;
3183  }
3184
3185  /**
3186   * When false we need explicit <code>@GeneratedValue</code> mapping to assign
3187   * Identity or Sequence generated values. When true Id properties are automatically
3188   * assigned Identity or Sequence without the GeneratedValue mapping.
3189   */
3190  public boolean isIdGeneratorAutomatic() {
3191    return idGeneratorAutomatic;
3192  }
3193
3194  /**
3195   * Set to false such that Id properties require explicit <code>@GeneratedValue</code>
3196   * mapping before they are assigned Identity or Sequence generation based on platform.
3197   */
3198  public void setIdGeneratorAutomatic(boolean idGeneratorAutomatic) {
3199    this.idGeneratorAutomatic = idGeneratorAutomatic;
3200  }
3201
3202  /**
3203   * Return true if query plan capture is enabled.
3204   */
3205  public boolean isQueryPlanEnable() {
3206    return queryPlanEnable;
3207  }
3208
3209  /**
3210   * Set to true to enable query plan capture.
3211   */
3212  public void setQueryPlanEnable(boolean queryPlanEnable) {
3213    this.queryPlanEnable = queryPlanEnable;
3214  }
3215
3216  /**
3217   * Return the query plan collection threshold in microseconds.
3218   */
3219  public long getQueryPlanThresholdMicros() {
3220    return queryPlanThresholdMicros;
3221  }
3222
3223  /**
3224   * Set the query plan collection threshold in microseconds.
3225   * <p>
3226   * Queries executing slower than this will have bind values captured such that later
3227   * the query plan can be captured and reported.
3228   */
3229  public void setQueryPlanThresholdMicros(long queryPlanThresholdMicros) {
3230    this.queryPlanThresholdMicros = queryPlanThresholdMicros;
3231  }
3232
3233  /**
3234   * Return true if periodic capture of query plans is enabled.
3235   */
3236  public boolean isQueryPlanCapture() {
3237    return queryPlanCapture;
3238  }
3239
3240  /**
3241   * Set to true to turn on periodic capture of query plans.
3242   */
3243  public void setQueryPlanCapture(boolean queryPlanCapture) {
3244    this.queryPlanCapture = queryPlanCapture;
3245  }
3246
3247  /**
3248   * Return the frequency to capture query plans.
3249   */
3250  public long getQueryPlanCapturePeriodSecs() {
3251    return queryPlanCapturePeriodSecs;
3252  }
3253
3254  /**
3255   * Set the frequency in seconds to capture query plans.
3256   */
3257  public void setQueryPlanCapturePeriodSecs(long queryPlanCapturePeriodSecs) {
3258    this.queryPlanCapturePeriodSecs = queryPlanCapturePeriodSecs;
3259  }
3260
3261  /**
3262   * Return the time after which a capture query plans request will
3263   * stop capturing more query plans.
3264   * <p>
3265   * Effectively this controls the amount of load/time we want to
3266   * allow for query plan capture.
3267   */
3268  public long getQueryPlanCaptureMaxTimeMillis() {
3269    return queryPlanCaptureMaxTimeMillis;
3270  }
3271
3272  /**
3273   * Set the time after which a capture query plans request will
3274   * stop capturing more query plans.
3275   * <p>
3276   * Effectively this controls the amount of load/time we want to
3277   * allow for query plan capture.
3278   */
3279  public void setQueryPlanCaptureMaxTimeMillis(long queryPlanCaptureMaxTimeMillis) {
3280    this.queryPlanCaptureMaxTimeMillis = queryPlanCaptureMaxTimeMillis;
3281  }
3282
3283  /**
3284   * Return the max number of query plans captured per request.
3285   */
3286  public int getQueryPlanCaptureMaxCount() {
3287    return queryPlanCaptureMaxCount;
3288  }
3289
3290  /**
3291   * Set the max number of query plans captured per request.
3292   */
3293  public void setQueryPlanCaptureMaxCount(int queryPlanCaptureMaxCount) {
3294    this.queryPlanCaptureMaxCount = queryPlanCaptureMaxCount;
3295  }
3296
3297  /**
3298   * Return the listener used to process captured query plans.
3299   */
3300  public QueryPlanListener getQueryPlanListener() {
3301    return queryPlanListener;
3302  }
3303
3304  /**
3305   * Set the listener used to process captured query plans.
3306   */
3307  public void setQueryPlanListener(QueryPlanListener queryPlanListener) {
3308    this.queryPlanListener = queryPlanListener;
3309  }
3310
3311  /**
3312   * Return true if metrics should be dumped when the server is shutdown.
3313   */
3314  public boolean isDumpMetricsOnShutdown() {
3315    return dumpMetricsOnShutdown;
3316  }
3317
3318  /**
3319   * Set to true if metrics should be dumped when the server is shutdown.
3320   */
3321  public void setDumpMetricsOnShutdown(boolean dumpMetricsOnShutdown) {
3322    this.dumpMetricsOnShutdown = dumpMetricsOnShutdown;
3323  }
3324
3325  /**
3326   * Return the options for dumping metrics.
3327   */
3328  public String getDumpMetricsOptions() {
3329    return dumpMetricsOptions;
3330  }
3331
3332  /**
3333   * Include 'sql' or 'hash' in options such that they are included in the output.
3334   *
3335   * @param dumpMetricsOptions Example "sql,hash", "sql"
3336   */
3337  public void setDumpMetricsOptions(String dumpMetricsOptions) {
3338    this.dumpMetricsOptions = dumpMetricsOptions;
3339  }
3340
3341  /**
3342   * Return true if entity classes should be loaded and registered via ModuleInfoLoader.
3343   * <p>
3344   * When false we either register entity classes via application code or use classpath
3345   * scanning to find and register entity classes.
3346   */
3347  public boolean isAutoLoadModuleInfo() {
3348    return loadModuleInfo && classes.isEmpty();
3349  }
3350
3351  /**
3352   * Set false to turn off automatic registration of entity beans.
3353   * <p>
3354   * When using query beans that also generates a module info class that
3355   * can register the entity bean classes (to avoid classpath scanning).
3356   * This is on by default and setting this to false turns it off.
3357   */
3358  public void setLoadModuleInfo(boolean loadModuleInfo) {
3359    this.loadModuleInfo = loadModuleInfo;
3360  }
3361
3362  public enum UuidVersion {
3363    VERSION4,
3364    VERSION1,
3365    VERSION1RND
3366  }
3367}