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   * <p>
1551   * For Postgres pgjdbc version 42.3.0 should be used with datasource property
1552   * <em>quoteReturningIdentifiers</em> set to <em>false</em> (refer #2303).
1553   */
1554  public void setAllQuotedIdentifiers(boolean allQuotedIdentifiers) {
1555    platformConfig.setAllQuotedIdentifiers(allQuotedIdentifiers);
1556    if (allQuotedIdentifiers) {
1557      adjustNamingConventionForAllQuoted();
1558    }
1559  }
1560
1561  private void adjustNamingConventionForAllQuoted() {
1562    if (namingConvention instanceof UnderscoreNamingConvention) {
1563      // we need to use matching naming convention
1564      this.namingConvention = new MatchingNamingConvention();
1565    }
1566  }
1567
1568  /**
1569   * Return true if this Database is a Document store only instance (has no JDBC DB).
1570   */
1571  public boolean isDocStoreOnly() {
1572    return docStoreOnly;
1573  }
1574
1575  /**
1576   * Set to true if this Database is Document store only instance (has no JDBC DB).
1577   */
1578  public void setDocStoreOnly(boolean docStoreOnly) {
1579    this.docStoreOnly = docStoreOnly;
1580  }
1581
1582  /**
1583   * Return the configuration for the ElasticSearch integration.
1584   */
1585  public DocStoreConfig getDocStoreConfig() {
1586    return docStoreConfig;
1587  }
1588
1589  /**
1590   * Set the configuration for the ElasticSearch integration.
1591   */
1592  public void setDocStoreConfig(DocStoreConfig docStoreConfig) {
1593    this.docStoreConfig = docStoreConfig;
1594  }
1595
1596  /**
1597   * Return the constraint naming convention used in DDL generation.
1598   */
1599  public DbConstraintNaming getConstraintNaming() {
1600    return platformConfig.getConstraintNaming();
1601  }
1602
1603  /**
1604   * Set the constraint naming convention used in DDL generation.
1605   */
1606  public void setConstraintNaming(DbConstraintNaming constraintNaming) {
1607    platformConfig.setConstraintNaming(constraintNaming);
1608  }
1609
1610  /**
1611   * Return the configuration for AutoTune.
1612   */
1613  public AutoTuneConfig getAutoTuneConfig() {
1614    return autoTuneConfig;
1615  }
1616
1617  /**
1618   * Set the configuration for AutoTune.
1619   */
1620  public void setAutoTuneConfig(AutoTuneConfig autoTuneConfig) {
1621    this.autoTuneConfig = autoTuneConfig;
1622  }
1623
1624  /**
1625   * Return true if the startup DataSource check should be skipped.
1626   */
1627  public boolean skipDataSourceCheck() {
1628    return skipDataSourceCheck;
1629  }
1630
1631  /**
1632   * Set to true to skip the startup DataSource check.
1633   */
1634  public void setSkipDataSourceCheck(boolean skipDataSourceCheck) {
1635    this.skipDataSourceCheck = skipDataSourceCheck;
1636  }
1637
1638  /**
1639   * Return the DataSource.
1640   */
1641  public DataSource getDataSource() {
1642    return dataSource;
1643  }
1644
1645  /**
1646   * Set a DataSource.
1647   */
1648  public void setDataSource(DataSource dataSource) {
1649    this.dataSource = dataSource;
1650  }
1651
1652  /**
1653   * Return the read only DataSource.
1654   */
1655  public DataSource getReadOnlyDataSource() {
1656    return readOnlyDataSource;
1657  }
1658
1659  /**
1660   * Set the read only DataSource.
1661   * <p>
1662   * Note that the DataSource is expected to use AutoCommit true mode avoiding the need
1663   * for explicit commit (or rollback).
1664   * <p>
1665   * This read only DataSource will be used for implicit query only transactions. It is not
1666   * used if the transaction is created explicitly or if the query is an update or delete query.
1667   */
1668  public void setReadOnlyDataSource(DataSource readOnlyDataSource) {
1669    this.readOnlyDataSource = readOnlyDataSource;
1670  }
1671
1672  /**
1673   * Return the configuration to build a DataSource using Ebean's own DataSource
1674   * implementation.
1675   */
1676  public DataSourceConfig getDataSourceConfig() {
1677    return dataSourceConfig;
1678  }
1679
1680  /**
1681   * Set the configuration required to build a DataSource using Ebean's own
1682   * DataSource implementation.
1683   */
1684  public void setDataSourceConfig(DataSourceConfig dataSourceConfig) {
1685    this.dataSourceConfig = dataSourceConfig;
1686  }
1687
1688  /**
1689   * Return true if Ebean should create a DataSource for use with implicit read only transactions.
1690   */
1691  public boolean isAutoReadOnlyDataSource() {
1692    return autoReadOnlyDataSource;
1693  }
1694
1695  /**
1696   * Set to true if Ebean should create a DataSource for use with implicit read only transactions.
1697   */
1698  public void setAutoReadOnlyDataSource(boolean autoReadOnlyDataSource) {
1699    this.autoReadOnlyDataSource = autoReadOnlyDataSource;
1700  }
1701
1702  /**
1703   * Return the configuration for the read only DataSource.
1704   * <p>
1705   * This is only used if autoReadOnlyDataSource is true.
1706   * <p>
1707   * The driver, url, username and password default to the configuration for the main DataSource if they are not
1708   * set on this configuration. This means there is actually no need to set any configuration here and we only
1709   * set configuration for url, username and password etc if it is different from the main DataSource.
1710   */
1711  public DataSourceConfig getReadOnlyDataSourceConfig() {
1712    return readOnlyDataSourceConfig;
1713  }
1714
1715  /**
1716   * Set the configuration for the read only DataSource.
1717   */
1718  public void setReadOnlyDataSourceConfig(DataSourceConfig readOnlyDataSourceConfig) {
1719    this.readOnlyDataSourceConfig = readOnlyDataSourceConfig;
1720  }
1721
1722  /**
1723   * Return the JNDI name of the DataSource to use.
1724   */
1725  public String getDataSourceJndiName() {
1726    return dataSourceJndiName;
1727  }
1728
1729  /**
1730   * Set the JNDI name of the DataSource to use.
1731   * <p>
1732   * By default a prefix of "java:comp/env/jdbc/" is used to lookup the
1733   * DataSource. This prefix is not used if dataSourceJndiName starts with
1734   * "java:".
1735   */
1736  public void setDataSourceJndiName(String dataSourceJndiName) {
1737    this.dataSourceJndiName = dataSourceJndiName;
1738  }
1739
1740  /**
1741   * Return a value used to represent TRUE in the database.
1742   * <p>
1743   * This is used for databases that do not support boolean natively.
1744   * <p>
1745   * The value returned is either a Integer or a String (e.g. "1", or "T").
1746   */
1747  public String getDatabaseBooleanTrue() {
1748    return platformConfig.getDatabaseBooleanTrue();
1749  }
1750
1751  /**
1752   * Set the value to represent TRUE in the database.
1753   * <p>
1754   * This is used for databases that do not support boolean natively.
1755   * <p>
1756   * The value set is either a Integer or a String (e.g. "1", or "T").
1757   */
1758  public void setDatabaseBooleanTrue(String databaseTrue) {
1759    platformConfig.setDatabaseBooleanTrue(databaseTrue);
1760  }
1761
1762  /**
1763   * Return a value used to represent FALSE in the database.
1764   * <p>
1765   * This is used for databases that do not support boolean natively.
1766   * <p>
1767   * The value returned is either a Integer or a String (e.g. "0", or "F").
1768   */
1769  public String getDatabaseBooleanFalse() {
1770    return platformConfig.getDatabaseBooleanFalse();
1771  }
1772
1773  /**
1774   * Set the value to represent FALSE in the database.
1775   * <p>
1776   * This is used for databases that do not support boolean natively.
1777   * <p>
1778   * The value set is either a Integer or a String (e.g. "0", or "F").
1779   */
1780  public void setDatabaseBooleanFalse(String databaseFalse) {
1781    this.platformConfig.setDatabaseBooleanFalse(databaseFalse);
1782  }
1783
1784  /**
1785   * Return the number of DB sequence values that should be preallocated.
1786   */
1787  public int getDatabaseSequenceBatchSize() {
1788    return platformConfig.getDatabaseSequenceBatchSize();
1789  }
1790
1791  /**
1792   * Set the number of DB sequence values that should be preallocated and cached
1793   * by Ebean.
1794   * <p>
1795   * This is only used for DB's that use sequences and is a performance
1796   * optimisation. This reduces the number of times Ebean needs to get a
1797   * sequence value from the Database reducing network chatter.
1798   * <p>
1799   * By default this value is 10 so when we need another Id (and don't have one
1800   * in our cache) Ebean will fetch 10 id's from the database. Note that when
1801   * the cache drops to have full (which is 5 by default) Ebean will fetch
1802   * another batch of Id's in a background thread.
1803   */
1804  public void setDatabaseSequenceBatch(int databaseSequenceBatchSize) {
1805    this.platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
1806  }
1807
1808  /**
1809   * Return the database platform name (can be null).
1810   * <p>
1811   * If null then the platform is determined automatically via the JDBC driver
1812   * information.
1813   */
1814  public String getDatabasePlatformName() {
1815    return databasePlatformName;
1816  }
1817
1818  /**
1819   * Explicitly set the database platform name
1820   * <p>
1821   * If none is set then the platform is determined automatically via the JDBC
1822   * driver information.
1823   * <p>
1824   * This can be used when the Database Platform can not be automatically
1825   * detected from the JDBC driver (possibly 3rd party JDBC driver). It is also
1826   * useful when you want to do offline DDL generation for a database platform
1827   * that you don't have access to.
1828   * <p>
1829   * Values are oracle, h2, postgres, mysql, sqlserver16, sqlserver17.
1830   */
1831  public void setDatabasePlatformName(String databasePlatformName) {
1832    this.databasePlatformName = databasePlatformName;
1833  }
1834
1835  /**
1836   * Return the database platform to use for this database.
1837   */
1838  public DatabasePlatform getDatabasePlatform() {
1839    return databasePlatform;
1840  }
1841
1842  /**
1843   * Explicitly set the database platform to use.
1844   * <p>
1845   * If none is set then the platform is determined via the databasePlatformName
1846   * or automatically via the JDBC driver information.
1847   */
1848  public void setDatabasePlatform(DatabasePlatform databasePlatform) {
1849    this.databasePlatform = databasePlatform;
1850  }
1851
1852  /**
1853   * Return the preferred DB platform IdType.
1854   */
1855  public IdType getIdType() {
1856    return platformConfig.getIdType();
1857  }
1858
1859  /**
1860   * Set the preferred DB platform IdType.
1861   */
1862  public void setIdType(IdType idType) {
1863    this.platformConfig.setIdType(idType);
1864  }
1865
1866  /**
1867   * Return the EncryptKeyManager.
1868   */
1869  public EncryptKeyManager getEncryptKeyManager() {
1870    return encryptKeyManager;
1871  }
1872
1873  /**
1874   * Set the EncryptKeyManager.
1875   * <p>
1876   * This is required when you want to use encrypted properties.
1877   * <p>
1878   * You can also set this in ebean.proprerties:
1879   * <p>
1880   * <pre>{@code
1881   * # set via ebean.properties
1882   * ebean.encryptKeyManager=org.avaje.tests.basic.encrypt.BasicEncyptKeyManager
1883   * }</pre>
1884   */
1885  public void setEncryptKeyManager(EncryptKeyManager encryptKeyManager) {
1886    this.encryptKeyManager = encryptKeyManager;
1887  }
1888
1889  /**
1890   * Return the EncryptDeployManager.
1891   * <p>
1892   * This is optionally used to programmatically define which columns are
1893   * encrypted instead of using the {@link Encrypted} Annotation.
1894   */
1895  public EncryptDeployManager getEncryptDeployManager() {
1896    return encryptDeployManager;
1897  }
1898
1899  /**
1900   * Set the EncryptDeployManager.
1901   * <p>
1902   * This is optionally used to programmatically define which columns are
1903   * encrypted instead of using the {@link Encrypted} Annotation.
1904   */
1905  public void setEncryptDeployManager(EncryptDeployManager encryptDeployManager) {
1906    this.encryptDeployManager = encryptDeployManager;
1907  }
1908
1909  /**
1910   * Return the Encryptor used to encrypt data on the java client side (as
1911   * opposed to DB encryption functions).
1912   */
1913  public Encryptor getEncryptor() {
1914    return encryptor;
1915  }
1916
1917  /**
1918   * Set the Encryptor used to encrypt data on the java client side (as opposed
1919   * to DB encryption functions).
1920   * <p>
1921   * Ebean has a default implementation that it will use if you do not set your
1922   * own Encryptor implementation.
1923   */
1924  public void setEncryptor(Encryptor encryptor) {
1925    this.encryptor = encryptor;
1926  }
1927
1928  /**
1929   * Return true if the Database instance should be created in offline mode.
1930   */
1931  public boolean isDbOffline() {
1932    return dbOffline;
1933  }
1934
1935  /**
1936   * Set to true if the Database instance should be created in offline mode.
1937   * <p>
1938   * Typically used to create an Database instance for DDL Migration generation
1939   * without requiring a real DataSource / Database to connect to.
1940   */
1941  public void setDbOffline(boolean dbOffline) {
1942    this.dbOffline = dbOffline;
1943  }
1944
1945  /**
1946   * Return the DbEncrypt used to encrypt and decrypt properties.
1947   * <p>
1948   * Note that if this is not set then the DbPlatform may already have a
1949   * DbEncrypt set and that will be used.
1950   */
1951  public DbEncrypt getDbEncrypt() {
1952    return dbEncrypt;
1953  }
1954
1955  /**
1956   * Set the DbEncrypt used to encrypt and decrypt properties.
1957   * <p>
1958   * Note that if this is not set then the DbPlatform may already have a
1959   * DbEncrypt set (H2, MySql, Postgres and Oracle platforms have a DbEncrypt)
1960   */
1961  public void setDbEncrypt(DbEncrypt dbEncrypt) {
1962    this.dbEncrypt = dbEncrypt;
1963  }
1964
1965  /**
1966   * Return the configuration for DB types (such as UUID and custom mappings).
1967   */
1968  public PlatformConfig getPlatformConfig() {
1969    return platformConfig;
1970  }
1971
1972  /**
1973   * Set the configuration for DB platform (such as UUID and custom mappings).
1974   */
1975  public void setPlatformConfig(PlatformConfig platformConfig) {
1976    this.platformConfig = platformConfig;
1977  }
1978
1979  /**
1980   * Set the DB type used to store UUID.
1981   */
1982  public void setDbUuid(PlatformConfig.DbUuid dbUuid) {
1983    this.platformConfig.setDbUuid(dbUuid);
1984  }
1985
1986  /**
1987   * Returns the UUID version mode.
1988   */
1989  public UuidVersion getUuidVersion() {
1990    return uuidVersion;
1991  }
1992
1993  /**
1994   * Sets the UUID version mode.
1995   */
1996  public void setUuidVersion(UuidVersion uuidVersion) {
1997    this.uuidVersion = uuidVersion;
1998  }
1999
2000  /**
2001   * Return the UUID state file.
2002   */
2003  public String getUuidStateFile() {
2004    if (uuidStateFile == null || uuidStateFile.isEmpty()) {
2005      // by default, add servername...
2006      uuidStateFile = name + "-uuid.state";
2007      // and store it in the user's home directory
2008      String homeDir = System.getProperty("user.home");
2009      if (homeDir != null && homeDir.isEmpty()) {
2010        uuidStateFile = homeDir + "/.ebean/" + uuidStateFile;
2011      }
2012    }
2013    return uuidStateFile;
2014  }
2015
2016  /**
2017   * Set the UUID state file.
2018   */
2019  public void setUuidStateFile(String uuidStateFile) {
2020    this.uuidStateFile = uuidStateFile;
2021  }
2022
2023  /**
2024   * Return true if LocalTime should be persisted with nanos precision.
2025   */
2026  public boolean isLocalTimeWithNanos() {
2027    return localTimeWithNanos;
2028  }
2029
2030  /**
2031   * Set to true if LocalTime should be persisted with nanos precision.
2032   * <p>
2033   * Otherwise it is persisted using java.sql.Time which is seconds precision.
2034   */
2035  public void setLocalTimeWithNanos(boolean localTimeWithNanos) {
2036    this.localTimeWithNanos = localTimeWithNanos;
2037  }
2038
2039  /**
2040   * Return true if Duration should be persisted with nanos precision (SQL DECIMAL).
2041   * <p>
2042   * Otherwise it is persisted with second precision (SQL INTEGER).
2043   */
2044  public boolean isDurationWithNanos() {
2045    return durationWithNanos;
2046  }
2047
2048  /**
2049   * Set to true if Duration should be persisted with nanos precision (SQL DECIMAL).
2050   * <p>
2051   * Otherwise it is persisted with second precision (SQL INTEGER).
2052   */
2053  public void setDurationWithNanos(boolean durationWithNanos) {
2054    this.durationWithNanos = durationWithNanos;
2055  }
2056
2057  /**
2058   * Set to true to run DB migrations on server start.
2059   * <p>
2060   * This is the same as config.getMigrationConfig().setRunMigration(). We have added this method here
2061   * as it is often the only thing we need to configure for migrations.
2062   */
2063  public void setRunMigration(boolean runMigration) {
2064    this.runMigration = runMigration;
2065  }
2066
2067  /**
2068   * Return true if the DB migration should run on server start.
2069   */
2070  public boolean isRunMigration() {
2071    final String run = System.getProperty("ebean.migration.run");
2072    return (run != null) ? Boolean.parseBoolean(run) : runMigration;
2073  }
2074
2075  /**
2076   * Set to true to generate the "create all" DDL on startup.
2077   * <p>
2078   * Typically we want this on when we are running tests locally (and often using H2)
2079   * and we want to create the full DB schema from scratch to run tests.
2080   */
2081  public void setDdlGenerate(boolean ddlGenerate) {
2082    this.ddlGenerate = ddlGenerate;
2083  }
2084
2085  /**
2086   * Set to true to run the generated "create all DDL" on startup.
2087   * <p>
2088   * Typically we want this on when we are running tests locally (and often using H2)
2089   * and we want to create the full DB schema from scratch to run tests.
2090   */
2091  public void setDdlRun(boolean ddlRun) {
2092    this.ddlRun = ddlRun;
2093  }
2094
2095  /**
2096   * Set to false if you not want to run the extra-ddl.xml scripts. (default = true)
2097   * <p>
2098   * Typically we want this on when we are running tests.
2099   */
2100  public void setDdlExtra(boolean ddlExtra) {
2101    this.ddlExtra = ddlExtra;
2102  }
2103
2104
2105  /**
2106   * Return true if the "drop all ddl" should be skipped.
2107   * <p>
2108   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
2109   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
2110   */
2111  public boolean isDdlCreateOnly() {
2112    return ddlCreateOnly;
2113  }
2114
2115  /**
2116   * Set to true if the "drop all ddl" should be skipped.
2117   * <p>
2118   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
2119   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
2120   */
2121  public void setDdlCreateOnly(boolean ddlCreateOnly) {
2122    this.ddlCreateOnly = ddlCreateOnly;
2123  }
2124
2125  /**
2126   * Return SQL script to execute after the "create all" DDL has been run.
2127   * <p>
2128   * Typically this is a sql script that inserts test seed data when running tests.
2129   * Place a sql script in src/test/resources that inserts test seed data.
2130   */
2131  public String getDdlSeedSql() {
2132    return ddlSeedSql;
2133  }
2134
2135  /**
2136   * Set a SQL script to execute after the "create all" DDL has been run.
2137   * <p>
2138   * Typically this is a sql script that inserts test seed data when running tests.
2139   * Place a sql script in src/test/resources that inserts test seed data.
2140   */
2141  public void setDdlSeedSql(String ddlSeedSql) {
2142    this.ddlSeedSql = ddlSeedSql;
2143  }
2144
2145  /**
2146   * Return a SQL script to execute before the "create all" DDL has been run.
2147   */
2148  public String getDdlInitSql() {
2149    return ddlInitSql;
2150  }
2151
2152  /**
2153   * Set a SQL script to execute before the "create all" DDL has been run.
2154   */
2155  public void setDdlInitSql(String ddlInitSql) {
2156    this.ddlInitSql = ddlInitSql;
2157  }
2158
2159  /**
2160   * Return true if the DDL should be generated.
2161   */
2162  public boolean isDdlGenerate() {
2163    return ddlGenerate;
2164  }
2165
2166  /**
2167   * Return true if the DDL should be run.
2168   */
2169  public boolean isDdlRun() {
2170    return ddlRun;
2171  }
2172
2173  /**
2174   * Return true, if extra-ddl.xml should be executed.
2175   */
2176  public boolean isDdlExtra() {
2177    return ddlExtra;
2178  }
2179
2180  /**
2181   * Set the header to use with DDL generation.
2182   */
2183  public void setDdlHeader(String ddlHeader) {
2184    this.ddlHeader = ddlHeader;
2185  }
2186
2187  /**
2188   * Return the header to use with DDL generation.
2189   */
2190  public String getDdlHeader() {
2191    if (ddlHeader != null && !ddlHeader.isEmpty()) {
2192      String header = ddlHeader.replace("${version}", EbeanVersion.getVersion());
2193      header = header.replace("${timestamp}", ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT));
2194      return header;
2195    }
2196    return ddlHeader;
2197  }
2198
2199  /**
2200   * Return true if strict mode is used which includes a check that non-null columns have a default value.
2201   */
2202  public boolean isDdlStrictMode() {
2203    return ddlStrictMode;
2204  }
2205
2206  /**
2207   * Set to false to turn off strict mode allowing non-null columns to not have a default value.
2208   */
2209  public void setDdlStrictMode(boolean ddlStrictMode) {
2210    this.ddlStrictMode = ddlStrictMode;
2211  }
2212
2213  /**
2214   * Return a comma and equals delimited placeholders that are substituted in DDL scripts.
2215   */
2216  public String getDdlPlaceholders() {
2217    return ddlPlaceholders;
2218  }
2219
2220  /**
2221   * Set a comma and equals delimited placeholders that are substituted in DDL scripts.
2222   */
2223  public void setDdlPlaceholders(String ddlPlaceholders) {
2224    this.ddlPlaceholders = ddlPlaceholders;
2225  }
2226
2227  /**
2228   * Return a map of placeholder values that are substituted in DDL scripts.
2229   */
2230  public Map<String, String> getDdlPlaceholderMap() {
2231    return ddlPlaceholderMap;
2232  }
2233
2234  /**
2235   * Set a map of placeholder values that are substituted in DDL scripts.
2236   */
2237  public void setDdlPlaceholderMap(Map<String, String> ddlPlaceholderMap) {
2238    this.ddlPlaceholderMap = ddlPlaceholderMap;
2239  }
2240
2241  /**
2242   * Return true if the class path search should be disabled.
2243   */
2244  public boolean isDisableClasspathSearch() {
2245    return disableClasspathSearch;
2246  }
2247
2248  /**
2249   * Set to true to disable the class path search even for the case where no entity bean classes
2250   * have been registered. This can be used to start an Database instance just to use the
2251   * SQL functions such as SqlQuery, SqlUpdate etc.
2252   */
2253  public void setDisableClasspathSearch(boolean disableClasspathSearch) {
2254    this.disableClasspathSearch = disableClasspathSearch;
2255  }
2256
2257  /**
2258   * Return the mode to use for Joda LocalTime support 'normal' or 'utc'.
2259   */
2260  public String getJodaLocalTimeMode() {
2261    return jodaLocalTimeMode;
2262  }
2263
2264  /**
2265   * Set the mode to use for Joda LocalTime support 'normal' or 'utc'.
2266   */
2267  public void setJodaLocalTimeMode(String jodaLocalTimeMode) {
2268    this.jodaLocalTimeMode = jodaLocalTimeMode;
2269  }
2270
2271  /**
2272   * Programmatically add classes (typically entities) that this server should
2273   * use.
2274   * <p>
2275   * The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
2276   * BeanFinder or BeanPersistController.
2277   * <p>
2278   * If no classes are specified then the classes are found automatically via
2279   * searching the class path.
2280   * <p>
2281   * Alternatively the classes can be added via {@link #setClasses(List)}.
2282   *
2283   * @param cls the entity type (or other type) that should be registered by this
2284   *            database.
2285   */
2286  public void addClass(Class<?> cls) {
2287    classes.add(cls);
2288  }
2289
2290  /**
2291   * Register all the classes (typically entity classes).
2292   */
2293  public void addAll(List<Class<?>> classList) {
2294    if (classList != null && !classList.isEmpty()) {
2295      classes.addAll(classList);
2296    }
2297  }
2298
2299  /**
2300   * Add a package to search for entities via class path search.
2301   * <p>
2302   * This is only used if classes have not been explicitly specified.
2303   */
2304  public void addPackage(String packageName) {
2305    packages.add(packageName);
2306  }
2307
2308  /**
2309   * Return packages to search for entities via class path search.
2310   * <p>
2311   * This is only used if classes have not been explicitly specified.
2312   */
2313  public List<String> getPackages() {
2314    return packages;
2315  }
2316
2317  /**
2318   * Set packages to search for entities via class path search.
2319   * <p>
2320   * This is only used if classes have not been explicitly specified.
2321   */
2322  public void setPackages(List<String> packages) {
2323    this.packages = packages;
2324  }
2325
2326  /**
2327   * Set the list of classes (entities, listeners, scalarTypes etc) that should
2328   * be used for this database.
2329   * <p>
2330   * If no classes are specified then the classes are found automatically via
2331   * searching the class path.
2332   * <p>
2333   * Alternatively the classes can contain added via {@link #addClass(Class)}.
2334   */
2335  public void setClasses(List<Class<?>> classes) {
2336    this.classes = classes;
2337  }
2338
2339  /**
2340   * Return the classes registered for this database. Typically this includes
2341   * entities and perhaps listeners.
2342   */
2343  public List<Class<?>> getClasses() {
2344    return classes;
2345  }
2346
2347  /**
2348   * Return true if L2 bean cache should be skipped once writes have occurred on a transaction.
2349   * <p>
2350   * This defaults to true and means that for "find by id" and "find by natural key"
2351   * queries that normally hit L2 bean cache automatically will not do so after a write/persist
2352   * on the transaction.
2353   * <p>
2354   * <pre>{@code
2355   *
2356   *   // assume Customer has L2 bean caching enabled ...
2357   *
2358   *   try (Transaction transaction = DB.beginTransaction()) {
2359   *
2360   *     // this uses L2 bean cache as the transaction
2361   *     // ... is considered "query only" at this point
2362   *     Customer.find.byId(42);
2363   *
2364   *     // transaction no longer "query only" once
2365   *     // ... a bean has been saved etc
2366   *     DB.save(someBean);
2367   *
2368   *     // will NOT use L2 bean cache as the transaction
2369   *     // ... is no longer considered "query only"
2370   *     Customer.find.byId(55);
2371   *
2372   *
2373   *
2374   *     // explicit control - please use L2 bean cache
2375   *
2376   *     transaction.setSkipCache(false);
2377   *     Customer.find.byId(77); // hit the l2 bean cache
2378   *
2379   *
2380   *     // explicit control - please don't use L2 bean cache
2381   *
2382   *     transaction.setSkipCache(true);
2383   *     Customer.find.byId(99); // skips l2 bean cache
2384   *
2385   *   }
2386   *
2387   * }</pre>
2388   *
2389   * @see Transaction#setSkipCache(boolean)
2390   */
2391  public boolean isSkipCacheAfterWrite() {
2392    return skipCacheAfterWrite;
2393  }
2394
2395  /**
2396   * Set to false when we still want to hit the cache after a write has occurred on a transaction.
2397   */
2398  public void setSkipCacheAfterWrite(boolean skipCacheAfterWrite) {
2399    this.skipCacheAfterWrite = skipCacheAfterWrite;
2400  }
2401
2402  /**
2403   * Returns true if updates in JDBC batch default to include all properties by default.
2404   */
2405  public boolean isUpdateAllPropertiesInBatch() {
2406    return updateAllPropertiesInBatch;
2407  }
2408
2409  /**
2410   * Set to false if by default updates in JDBC batch should not include all properties.
2411   * <p>
2412   * This mode can be explicitly set per transaction.
2413   *
2414   * @see Transaction#setUpdateAllLoadedProperties(boolean)
2415   */
2416  public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
2417    this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
2418  }
2419
2420  /**
2421   * Returns the resource directory.
2422   */
2423  public String getResourceDirectory() {
2424    return resourceDirectory;
2425  }
2426
2427  /**
2428   * Sets the resource directory.
2429   */
2430  public void setResourceDirectory(String resourceDirectory) {
2431    this.resourceDirectory = resourceDirectory;
2432  }
2433
2434  /**
2435   * Add a custom type mapping.
2436   * <p>
2437   * <pre>{@code
2438   *
2439   *   // set the default mapping for BigDecimal.class/decimal
2440   *   config.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
2441   *
2442   *   // set the default mapping for String.class/varchar but only for Postgres
2443   *   config.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES);
2444   *
2445   * }</pre>
2446   *
2447   * @param type             The DB type this mapping should apply to
2448   * @param columnDefinition The column definition that should be used
2449   * @param platform         Optionally specify the platform this mapping should apply to.
2450   */
2451  public void addCustomMapping(DbType type, String columnDefinition, Platform platform) {
2452    platformConfig.addCustomMapping(type, columnDefinition, platform);
2453  }
2454
2455  /**
2456   * Add a custom type mapping that applies to all platforms.
2457   * <p>
2458   * <pre>{@code
2459   *
2460   *   // set the default mapping for BigDecimal/decimal
2461   *   config.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
2462   *
2463   *   // set the default mapping for String/varchar
2464   *   config.addCustomMapping(DbType.VARCHAR, "text");
2465   *
2466   * }</pre>
2467   *
2468   * @param type             The DB type this mapping should apply to
2469   * @param columnDefinition The column definition that should be used
2470   */
2471  public void addCustomMapping(DbType type, String columnDefinition) {
2472    platformConfig.addCustomMapping(type, columnDefinition);
2473  }
2474
2475  /**
2476   * Register a BeanQueryAdapter instance.
2477   * <p>
2478   * Note alternatively you can use {@link #setQueryAdapters(List)} to set all
2479   * the BeanQueryAdapter instances.
2480   */
2481  public void add(BeanQueryAdapter beanQueryAdapter) {
2482    queryAdapters.add(beanQueryAdapter);
2483  }
2484
2485  /**
2486   * Return the BeanQueryAdapter instances.
2487   */
2488  public List<BeanQueryAdapter> getQueryAdapters() {
2489    return queryAdapters;
2490  }
2491
2492  /**
2493   * Register all the BeanQueryAdapter instances.
2494   * <p>
2495   * Note alternatively you can use {@link #add(BeanQueryAdapter)} to add
2496   * BeanQueryAdapter instances one at a time.
2497   */
2498  public void setQueryAdapters(List<BeanQueryAdapter> queryAdapters) {
2499    this.queryAdapters = queryAdapters;
2500  }
2501
2502  /**
2503   * Return the custom IdGenerator instances.
2504   */
2505  public List<IdGenerator> getIdGenerators() {
2506    return idGenerators;
2507  }
2508
2509  /**
2510   * Set the custom IdGenerator instances.
2511   */
2512  public void setIdGenerators(List<IdGenerator> idGenerators) {
2513    this.idGenerators = idGenerators;
2514  }
2515
2516  /**
2517   * Register a customer IdGenerator instance.
2518   */
2519  public void add(IdGenerator idGenerator) {
2520    idGenerators.add(idGenerator);
2521  }
2522
2523  /**
2524   * Register a BeanPersistController instance.
2525   * <p>
2526   * Note alternatively you can use {@link #setPersistControllers(List)} to set
2527   * all the BeanPersistController instances.
2528   */
2529  public void add(BeanPersistController beanPersistController) {
2530    persistControllers.add(beanPersistController);
2531  }
2532
2533  /**
2534   * Register a BeanPostLoad instance.
2535   * <p>
2536   * Note alternatively you can use {@link #setPostLoaders(List)} to set
2537   * all the BeanPostLoad instances.
2538   */
2539  public void add(BeanPostLoad postLoad) {
2540    postLoaders.add(postLoad);
2541  }
2542
2543  /**
2544   * Register a BeanPostConstructListener instance.
2545   * <p>
2546   * Note alternatively you can use {@link #setPostConstructListeners(List)} to set
2547   * all the BeanPostConstructListener instances.
2548   */
2549  public void add(BeanPostConstructListener listener) {
2550    postConstructListeners.add(listener);
2551  }
2552
2553  /**
2554   * Return the list of BeanFindController instances.
2555   */
2556  public List<BeanFindController> getFindControllers() {
2557    return findControllers;
2558  }
2559
2560  /**
2561   * Set the list of BeanFindController instances.
2562   */
2563  public void setFindControllers(List<BeanFindController> findControllers) {
2564    this.findControllers = findControllers;
2565  }
2566
2567  /**
2568   * Return the list of BeanPostLoader instances.
2569   */
2570  public List<BeanPostLoad> getPostLoaders() {
2571    return postLoaders;
2572  }
2573
2574  /**
2575   * Set the list of BeanPostLoader instances.
2576   */
2577  public void setPostLoaders(List<BeanPostLoad> postLoaders) {
2578    this.postLoaders = postLoaders;
2579  }
2580
2581  /**
2582   * Return the list of BeanPostLoader instances.
2583   */
2584  public List<BeanPostConstructListener> getPostConstructListeners() {
2585    return postConstructListeners;
2586  }
2587
2588  /**
2589   * Set the list of BeanPostLoader instances.
2590   */
2591  public void setPostConstructListeners(List<BeanPostConstructListener> listeners) {
2592    this.postConstructListeners = listeners;
2593  }
2594
2595  /**
2596   * Return the BeanPersistController instances.
2597   */
2598  public List<BeanPersistController> getPersistControllers() {
2599    return persistControllers;
2600  }
2601
2602  /**
2603   * Register all the BeanPersistController instances.
2604   * <p>
2605   * Note alternatively you can use {@link #add(BeanPersistController)} to add
2606   * BeanPersistController instances one at a time.
2607   */
2608  public void setPersistControllers(List<BeanPersistController> persistControllers) {
2609    this.persistControllers = persistControllers;
2610  }
2611
2612  /**
2613   * Register a BeanPersistListener instance.
2614   * <p>
2615   * Note alternatively you can use {@link #setPersistListeners(List)} to set
2616   * all the BeanPersistListener instances.
2617   */
2618  public void add(BeanPersistListener beanPersistListener) {
2619    persistListeners.add(beanPersistListener);
2620  }
2621
2622  /**
2623   * Return the BeanPersistListener instances.
2624   */
2625  public List<BeanPersistListener> getPersistListeners() {
2626    return persistListeners;
2627  }
2628
2629  /**
2630   * Add a BulkTableEventListener
2631   */
2632  public void add(BulkTableEventListener bulkTableEventListener) {
2633    bulkTableEventListeners.add(bulkTableEventListener);
2634  }
2635
2636  /**
2637   * Return the list of BulkTableEventListener instances.
2638   */
2639  public List<BulkTableEventListener> getBulkTableEventListeners() {
2640    return bulkTableEventListeners;
2641  }
2642
2643  /**
2644   * Add a ServerConfigStartup.
2645   */
2646  public void addServerConfigStartup(ServerConfigStartup configStartupListener) {
2647    configStartupListeners.add(configStartupListener);
2648  }
2649
2650  /**
2651   * Return the list of ServerConfigStartup instances.
2652   */
2653  public List<ServerConfigStartup> getServerConfigStartupListeners() {
2654    return configStartupListeners;
2655  }
2656
2657  /**
2658   * Register all the BeanPersistListener instances.
2659   * <p>
2660   * Note alternatively you can use {@link #add(BeanPersistListener)} to add
2661   * BeanPersistListener instances one at a time.
2662   */
2663  public void setPersistListeners(List<BeanPersistListener> persistListeners) {
2664    this.persistListeners = persistListeners;
2665  }
2666
2667  /**
2668   * Return the default PersistenceContextScope to be used if one is not explicitly set on a query.
2669   * <p/>
2670   * The PersistenceContextScope can specified on each query via {@link io.ebean
2671   * .Query#setPersistenceContextScope(io.ebean.PersistenceContextScope)}. If it
2672   * is not set on the query this default scope is used.
2673   *
2674   * @see Query#setPersistenceContextScope(PersistenceContextScope)
2675   */
2676  public PersistenceContextScope getPersistenceContextScope() {
2677    // if somehow null return TRANSACTION scope
2678    return persistenceContextScope == null ? PersistenceContextScope.TRANSACTION : persistenceContextScope;
2679  }
2680
2681  /**
2682   * Set the PersistenceContext scope to be used if one is not explicitly set on a query.
2683   * <p/>
2684   * This defaults to {@link PersistenceContextScope#TRANSACTION}.
2685   * <p/>
2686   * The PersistenceContextScope can specified on each query via {@link io.ebean
2687   * .Query#setPersistenceContextScope(io.ebean.PersistenceContextScope)}. If it
2688   * is not set on the query this scope is used.
2689   *
2690   * @see Query#setPersistenceContextScope(PersistenceContextScope)
2691   */
2692  public void setPersistenceContextScope(PersistenceContextScope persistenceContextScope) {
2693    this.persistenceContextScope = persistenceContextScope;
2694  }
2695
2696  /**
2697   * Return the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2698   * create new instances of plugins given a className.
2699   */
2700  public ClassLoadConfig getClassLoadConfig() {
2701    return classLoadConfig;
2702  }
2703
2704  /**
2705   * Set the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2706   * create new instances of plugins given a className.
2707   */
2708  public void setClassLoadConfig(ClassLoadConfig classLoadConfig) {
2709    this.classLoadConfig = classLoadConfig;
2710  }
2711
2712
2713
2714  /**
2715   * Load settings from application.properties, application.yaml and other sources.
2716   * <p>
2717   * Uses <code>avaje-config</code> to load configuration properties.  Goto https://avaje.io/config
2718   * for detail on how and where properties are loaded from.
2719   */
2720  public void loadFromProperties() {
2721    this.properties = Config.asProperties();
2722    configureFromProperties();
2723  }
2724
2725  /**
2726   * Load the settings from the given properties
2727   */
2728  public void loadFromProperties(Properties properties) {
2729    // keep the properties used for configuration so that these are available for plugins
2730    this.properties = Config.asConfiguration().eval(properties);
2731    configureFromProperties();
2732  }
2733
2734  /**
2735   * Load the settings from the given properties
2736   */
2737  private void configureFromProperties() {
2738    List<AutoConfigure> autoConfigures = autoConfiguration();
2739    loadSettings(new PropertiesWrapper("ebean", name, properties, classLoadConfig));
2740    for (AutoConfigure autoConfigure : autoConfigures) {
2741      autoConfigure.postConfigure(this);
2742    }
2743  }
2744
2745  /**
2746   * Use a 'plugin' to provide automatic configuration. Intended for automatic testing
2747   * configuration with Docker containers via ebean-test-config.
2748   */
2749  private List<AutoConfigure> autoConfiguration() {
2750    List<AutoConfigure> list = new ArrayList<>();
2751    for (AutoConfigure autoConfigure : ServiceLoader.load(AutoConfigure.class)) {
2752      autoConfigure.preConfigure(this);
2753      list.add(autoConfigure);
2754    }
2755    return list;
2756  }
2757
2758  /**
2759   * Return the properties that we used for configuration and were set via a call to loadFromProperties().
2760   */
2761  public Properties getProperties() {
2762    return properties;
2763  }
2764
2765  /**
2766   * loads the data source settings to preserve existing behaviour. IMHO, if someone has set the datasource config already,
2767   * they don't want the settings to be reloaded and reset. This allows a descending class to override this behaviour and prevent it
2768   * from happening.
2769   *
2770   * @param p - The defined property source passed to load settings
2771   */
2772  protected void loadDataSourceSettings(PropertiesWrapper p) {
2773    dataSourceConfig.loadSettings(p.properties, name);
2774    readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
2775  }
2776
2777  /**
2778   * This is broken out to allow overridden behaviour.
2779   */
2780  protected void loadDocStoreSettings(PropertiesWrapper p) {
2781    docStoreConfig.loadSettings(p);
2782  }
2783
2784  /**
2785   * This is broken out to allow overridden behaviour.
2786   */
2787  protected void loadAutoTuneSettings(PropertiesWrapper p) {
2788    autoTuneConfig.loadSettings(p);
2789  }
2790
2791  /**
2792   * Load the configuration settings from the properties file.
2793   */
2794  protected void loadSettings(PropertiesWrapper p) {
2795    dbSchema = p.get("dbSchema", dbSchema);
2796    profilingConfig.loadSettings(p, name);
2797    platformConfig.loadSettings(p);
2798    if (platformConfig.isAllQuotedIdentifiers()) {
2799      adjustNamingConventionForAllQuoted();
2800    }
2801    namingConvention = createNamingConvention(p, namingConvention);
2802    if (namingConvention != null) {
2803      namingConvention.loadFromProperties(p);
2804    }
2805    if (autoTuneConfig == null) {
2806      autoTuneConfig = new AutoTuneConfig();
2807    }
2808    loadAutoTuneSettings(p);
2809
2810    if (dataSourceConfig == null) {
2811      dataSourceConfig = new DataSourceConfig();
2812    }
2813    loadDataSourceSettings(p);
2814
2815    if (docStoreConfig == null) {
2816      docStoreConfig = new DocStoreConfig();
2817    }
2818    loadDocStoreSettings(p);
2819
2820    defaultServer = p.getBoolean("defaultServer", defaultServer);
2821    autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
2822    loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
2823    maxCallStack = p.getInt("maxCallStack", maxCallStack);
2824    dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
2825    dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
2826    queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
2827    slowQueryMillis = p.getLong("slowQueryMillis", slowQueryMillis);
2828    queryPlanEnable = p.getBoolean("queryPlan.enable", queryPlanEnable);
2829    queryPlanThresholdMicros = p.getLong("queryPlan.thresholdMicros", queryPlanThresholdMicros);
2830    queryPlanCapture = p.getBoolean("queryPlan.capture", queryPlanCapture);
2831    queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
2832    queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
2833    queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
2834    docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
2835    disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
2836    localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
2837    enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
2838    notifyL2CacheInForeground = p.getBoolean("notifyL2CacheInForeground", notifyL2CacheInForeground);
2839    useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
2840    useValidationNotNull = p.getBoolean("useValidationNotNull", useValidationNotNull);
2841    autoReadOnlyDataSource = p.getBoolean("autoReadOnlyDataSource", autoReadOnlyDataSource);
2842    idGeneratorAutomatic = p.getBoolean("idGeneratorAutomatic", idGeneratorAutomatic);
2843
2844    backgroundExecutorSchedulePoolSize = p.getInt("backgroundExecutorSchedulePoolSize", backgroundExecutorSchedulePoolSize);
2845    backgroundExecutorShutdownSecs = p.getInt("backgroundExecutorShutdownSecs", backgroundExecutorShutdownSecs);
2846    disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
2847    currentUserProvider = p.createInstance(CurrentUserProvider.class, "currentUserProvider", currentUserProvider);
2848    databasePlatform = p.createInstance(DatabasePlatform.class, "databasePlatform", databasePlatform);
2849    encryptKeyManager = p.createInstance(EncryptKeyManager.class, "encryptKeyManager", encryptKeyManager);
2850    encryptDeployManager = p.createInstance(EncryptDeployManager.class, "encryptDeployManager", encryptDeployManager);
2851    encryptor = p.createInstance(Encryptor.class, "encryptor", encryptor);
2852    dbEncrypt = p.createInstance(DbEncrypt.class, "dbEncrypt", dbEncrypt);
2853    dbOffline = p.getBoolean("dbOffline", dbOffline);
2854    serverCachePlugin = p.createInstance(ServerCachePlugin.class, "serverCachePlugin", serverCachePlugin);
2855
2856    String packagesProp = p.get("search.packages", p.get("packages", null));
2857    packages = getSearchList(packagesProp, packages);
2858
2859    skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
2860    updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
2861
2862    if (p.get("batch.mode") != null || p.get("persistBatching") != null) {
2863      throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
2864    }
2865
2866    persistBatch = p.getEnum(PersistBatch.class, "persistBatch", persistBatch);
2867    persistBatchOnCascade = p.getEnum(PersistBatch.class, "persistBatchOnCascade", persistBatchOnCascade);
2868
2869    int batchSize = p.getInt("batch.size", persistBatchSize);
2870    persistBatchSize = p.getInt("persistBatchSize", batchSize);
2871
2872    persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
2873
2874    changeLogAsync = p.getBoolean("changeLogAsync", changeLogAsync);
2875    changeLogIncludeInserts = p.getBoolean("changeLogIncludeInserts", changeLogIncludeInserts);
2876    expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
2877    expressionNativeIlike = p.getBoolean("expressionNativeIlike", expressionNativeIlike);
2878
2879    dataTimeZone = p.get("dataTimeZone", dataTimeZone);
2880    asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
2881    asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
2882    historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
2883    dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
2884    jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
2885    jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
2886    databasePlatformName = p.get("databasePlatformName", databasePlatformName);
2887    defaultOrderById = p.getBoolean("defaultOrderById", defaultOrderById);
2888
2889    uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
2890    uuidStateFile = p.get("uuidStateFile", uuidStateFile);
2891
2892    localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
2893    jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
2894
2895    defaultEnumType = p.getEnum(EnumType.class, "defaultEnumType", defaultEnumType);
2896    disableLazyLoading = p.getBoolean("disableLazyLoading", disableLazyLoading);
2897    lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
2898    queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
2899
2900    jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
2901    jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime);
2902    jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate);
2903    jsonMutationDetection = p.getEnum(MutationDetection.class, "jsonMutationDetection", jsonMutationDetection);
2904
2905    skipDataSourceCheck = p.getBoolean("skipDataSourceCheck", skipDataSourceCheck);
2906    runMigration = p.getBoolean("migration.run", runMigration);
2907    ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
2908    ddlRun = p.getBoolean("ddl.run", ddlRun);
2909    ddlExtra = p.getBoolean("ddl.extra", ddlExtra);
2910    ddlCreateOnly = p.getBoolean("ddl.createOnly", ddlCreateOnly);
2911    ddlInitSql = p.get("ddl.initSql", ddlInitSql);
2912    ddlSeedSql = p.get("ddl.seedSql", ddlSeedSql);
2913    ddlStrictMode = p.getBoolean("ddl.strictMode", ddlStrictMode);
2914    ddlPlaceholders = p.get("ddl.placeholders", ddlPlaceholders);
2915    ddlHeader = p.get("ddl.header", ddlHeader);
2916
2917    // read tenant-configuration from config:
2918    // tenant.mode = NONE | DB | SCHEMA | CATALOG | PARTITION
2919    String mode = p.get("tenant.mode");
2920    if (mode != null) {
2921      for (TenantMode value : TenantMode.values()) {
2922        if (value.name().equalsIgnoreCase(mode)) {
2923          tenantMode = value;
2924          break;
2925        }
2926      }
2927    }
2928
2929    currentTenantProvider = p.createInstance(CurrentTenantProvider.class, "tenant.currentTenantProvider", currentTenantProvider);
2930    tenantCatalogProvider = p.createInstance(TenantCatalogProvider.class, "tenant.catalogProvider", tenantCatalogProvider);
2931    tenantSchemaProvider = p.createInstance(TenantSchemaProvider.class, "tenant.schemaProvider", tenantSchemaProvider);
2932    tenantPartitionColumn = p.get("tenant.partitionColumn", tenantPartitionColumn);
2933    classes = getClasses(p);
2934
2935    String mappingsProp = p.get("mappingLocations", null);
2936    mappingLocations = getSearchList(mappingsProp, mappingLocations);
2937  }
2938
2939  private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
2940    NamingConvention nc = properties.createInstance(NamingConvention.class, "namingConvention", null);
2941    return (nc != null) ? nc : namingConvention;
2942  }
2943
2944  /**
2945   * Build the list of classes from the comma delimited string.
2946   *
2947   * @param properties the properties
2948   * @return the classes
2949   */
2950  private List<Class<?>> getClasses(PropertiesWrapper properties) {
2951    String classNames = properties.get("classes", null);
2952    if (classNames == null) {
2953      return classes;
2954    }
2955
2956    List<Class<?>> classList = new ArrayList<>();
2957    String[] split = StringHelper.splitNames(classNames);
2958    for (String cn : split) {
2959      if (!"class".equalsIgnoreCase(cn)) {
2960        try {
2961          classList.add(Class.forName(cn));
2962        } catch (ClassNotFoundException e) {
2963          String msg = "Error registering class [" + cn + "] from [" + classNames + "]";
2964          throw new RuntimeException(msg, e);
2965        }
2966      }
2967    }
2968    return classList;
2969  }
2970
2971  private List<String> getSearchList(String searchNames, List<String> defaultValue) {
2972    if (searchNames != null) {
2973      String[] entries = StringHelper.splitNames(searchNames);
2974      List<String> hitList = new ArrayList<>(entries.length);
2975      Collections.addAll(hitList, entries);
2976      return hitList;
2977    } else {
2978      return defaultValue;
2979    }
2980  }
2981
2982  /**
2983   * Return the PersistBatch mode to use for 'batchOnCascade' taking into account if the database
2984   * platform supports getGeneratedKeys in batch mode.
2985   */
2986  public PersistBatch appliedPersistBatchOnCascade() {
2987    if (persistBatchOnCascade == PersistBatch.INHERIT) {
2988      // use the platform default (ALL except SQL Server which has NONE)
2989      return databasePlatform.getPersistBatchOnCascade();
2990    }
2991    return persistBatchOnCascade;
2992  }
2993
2994  /**
2995   * Return the Jackson ObjectMapper.
2996   * <p>
2997   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
2998   */
2999  public Object getObjectMapper() {
3000    return objectMapper;
3001  }
3002
3003  /**
3004   * Set the Jackson ObjectMapper.
3005   * <p>
3006   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
3007   */
3008  public void setObjectMapper(Object objectMapper) {
3009    this.objectMapper = objectMapper;
3010  }
3011
3012  /**
3013   * Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
3014   */
3015  public boolean isExpressionEqualsWithNullAsNoop() {
3016    return expressionEqualsWithNullAsNoop;
3017  }
3018
3019  /**
3020   * Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
3021   * <p>
3022   * Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
3023   * ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
3024   * which will add "1=1" into the SQL rather than "is null".
3025   */
3026  public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
3027    this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
3028  }
3029
3030  /**
3031   * Return true if native ILIKE expression should be used if supported by the database platform (e.g. Postgres).
3032   */
3033  public boolean isExpressionNativeIlike() {
3034    return expressionNativeIlike;
3035  }
3036
3037  /**
3038   * Set to true to use native ILIKE expression if supported by the database platform (e.g. Postgres).
3039   */
3040  public void setExpressionNativeIlike(boolean expressionNativeIlike) {
3041    this.expressionNativeIlike = expressionNativeIlike;
3042  }
3043
3044  /**
3045   * Return the enabled L2 cache regions.
3046   */
3047  public String getEnabledL2Regions() {
3048    return enabledL2Regions;
3049  }
3050
3051  /**
3052   * Set the enabled L2 cache regions (comma delimited).
3053   */
3054  public void setEnabledL2Regions(String enabledL2Regions) {
3055    this.enabledL2Regions = enabledL2Regions;
3056  }
3057
3058  /**
3059   * Return true if L2 cache is disabled.
3060   */
3061  public boolean isDisableL2Cache() {
3062    return disableL2Cache;
3063  }
3064
3065  /**
3066   * Set to true to disable L2 caching. Typically useful in performance testing.
3067   */
3068  public void setDisableL2Cache(boolean disableL2Cache) {
3069    this.disableL2Cache = disableL2Cache;
3070  }
3071
3072  /**
3073   * Return true to use local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
3074   */
3075  public boolean isLocalOnlyL2Cache() {
3076    return localOnlyL2Cache;
3077  }
3078
3079  /**
3080   * Force the use of local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
3081   */
3082  public void setLocalOnlyL2Cache(boolean localOnlyL2Cache) {
3083    this.localOnlyL2Cache = localOnlyL2Cache;
3084  }
3085
3086  /**
3087   * Returns if we use javax.validation.constraints.NotNull
3088   */
3089  public boolean isUseValidationNotNull() {
3090    return useValidationNotNull;
3091  }
3092
3093  /**
3094   * Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code> or
3095   * <code>&x64;jakarta.validation.contstraints.NotNull</code>
3096   * with respect to generating a <code>NOT NULL</code> column.
3097   * <p>
3098   * Normally when Ebean sees javax NotNull annotation it means that column is defined as NOT NULL.
3099   * Set this to <code>false</code> and the javax NotNull annotation is effectively ignored (and
3100   * we instead use Ebean's own NotNull annotation or JPA Column(nullable=false) annotation.
3101   */
3102  public void setUseValidationNotNull(boolean useValidationNotNull) {
3103    this.useValidationNotNull = useValidationNotNull;
3104  }
3105
3106  /**
3107   * Return true if L2 cache notification should run in the foreground.
3108   */
3109  public boolean isNotifyL2CacheInForeground() {
3110    return notifyL2CacheInForeground;
3111  }
3112
3113  /**
3114   * Set this to true to run L2 cache notification in the foreground.
3115   * <p>
3116   * In general we don't want to do that as when we use a distributed cache (like Ignite, Hazelcast etc)
3117   * we are making network calls and we prefer to do this in background and not impact the response time
3118   * of the executing transaction.
3119   */
3120  public void setNotifyL2CacheInForeground(boolean notifyL2CacheInForeground) {
3121    this.notifyL2CacheInForeground = notifyL2CacheInForeground;
3122  }
3123
3124  /**
3125   * Return the time to live for ebean's internal query plan.
3126   */
3127  public int getQueryPlanTTLSeconds() {
3128    return queryPlanTTLSeconds;
3129  }
3130
3131  /**
3132   * Set the time to live for ebean's internal query plan.
3133   * <p>
3134   * This is the plan that knows how to execute the query, read the result
3135   * and collects execution metrics. By default this is set to 5 mins.
3136   */
3137  public void setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
3138    this.queryPlanTTLSeconds = queryPlanTTLSeconds;
3139  }
3140
3141  /**
3142   * Create a new PlatformConfig based of the one held but with overridden properties by reading
3143   * properties with the given path and prefix.
3144   * <p>
3145   * Typically used in Db Migration generation for many platform targets that might have different
3146   * configuration for IdType, UUID, quoted identifiers etc.
3147   *
3148   * @param propertiesPath The properties path used for loading and setting properties
3149   * @param platformPrefix The prefix used for loading and setting properties
3150   * @return A copy of the PlatformConfig with overridden properties
3151   */
3152  public PlatformConfig newPlatformConfig(String propertiesPath, String platformPrefix) {
3153    if (properties == null) {
3154      properties = new Properties();
3155    }
3156    PropertiesWrapper p = new PropertiesWrapper(propertiesPath, platformPrefix, properties, classLoadConfig);
3157    PlatformConfig config = new PlatformConfig(platformConfig);
3158    config.loadSettings(p);
3159    return config;
3160  }
3161
3162  /**
3163   * Add a mapping location to search for xml mapping via class path search.
3164   */
3165  public void addMappingLocation(String mappingLocation) {
3166    if (mappingLocations == null) {
3167      mappingLocations = new ArrayList<>();
3168    }
3169    mappingLocations.add(mappingLocation);
3170  }
3171
3172  /**
3173   * Return mapping locations to search for xml mapping via class path search.
3174   */
3175  public List<String> getMappingLocations() {
3176    return mappingLocations;
3177  }
3178
3179  /**
3180   * Set mapping locations to search for xml mapping via class path search.
3181   * <p>
3182   * This is only used if classes have not been explicitly specified.
3183   */
3184  public void setMappingLocations(List<String> mappingLocations) {
3185    this.mappingLocations = mappingLocations;
3186  }
3187
3188  /**
3189   * When false we need explicit <code>@GeneratedValue</code> mapping to assign
3190   * Identity or Sequence generated values. When true Id properties are automatically
3191   * assigned Identity or Sequence without the GeneratedValue mapping.
3192   */
3193  public boolean isIdGeneratorAutomatic() {
3194    return idGeneratorAutomatic;
3195  }
3196
3197  /**
3198   * Set to false such that Id properties require explicit <code>@GeneratedValue</code>
3199   * mapping before they are assigned Identity or Sequence generation based on platform.
3200   */
3201  public void setIdGeneratorAutomatic(boolean idGeneratorAutomatic) {
3202    this.idGeneratorAutomatic = idGeneratorAutomatic;
3203  }
3204
3205  /**
3206   * Return true if query plan capture is enabled.
3207   */
3208  public boolean isQueryPlanEnable() {
3209    return queryPlanEnable;
3210  }
3211
3212  /**
3213   * Set to true to enable query plan capture.
3214   */
3215  public void setQueryPlanEnable(boolean queryPlanEnable) {
3216    this.queryPlanEnable = queryPlanEnable;
3217  }
3218
3219  /**
3220   * Return the query plan collection threshold in microseconds.
3221   */
3222  public long getQueryPlanThresholdMicros() {
3223    return queryPlanThresholdMicros;
3224  }
3225
3226  /**
3227   * Set the query plan collection threshold in microseconds.
3228   * <p>
3229   * Queries executing slower than this will have bind values captured such that later
3230   * the query plan can be captured and reported.
3231   */
3232  public void setQueryPlanThresholdMicros(long queryPlanThresholdMicros) {
3233    this.queryPlanThresholdMicros = queryPlanThresholdMicros;
3234  }
3235
3236  /**
3237   * Return true if periodic capture of query plans is enabled.
3238   */
3239  public boolean isQueryPlanCapture() {
3240    return queryPlanCapture;
3241  }
3242
3243  /**
3244   * Set to true to turn on periodic capture of query plans.
3245   */
3246  public void setQueryPlanCapture(boolean queryPlanCapture) {
3247    this.queryPlanCapture = queryPlanCapture;
3248  }
3249
3250  /**
3251   * Return the frequency to capture query plans.
3252   */
3253  public long getQueryPlanCapturePeriodSecs() {
3254    return queryPlanCapturePeriodSecs;
3255  }
3256
3257  /**
3258   * Set the frequency in seconds to capture query plans.
3259   */
3260  public void setQueryPlanCapturePeriodSecs(long queryPlanCapturePeriodSecs) {
3261    this.queryPlanCapturePeriodSecs = queryPlanCapturePeriodSecs;
3262  }
3263
3264  /**
3265   * Return the time after which a capture query plans request will
3266   * stop capturing more query plans.
3267   * <p>
3268   * Effectively this controls the amount of load/time we want to
3269   * allow for query plan capture.
3270   */
3271  public long getQueryPlanCaptureMaxTimeMillis() {
3272    return queryPlanCaptureMaxTimeMillis;
3273  }
3274
3275  /**
3276   * Set the time after which a capture query plans request will
3277   * stop capturing more query plans.
3278   * <p>
3279   * Effectively this controls the amount of load/time we want to
3280   * allow for query plan capture.
3281   */
3282  public void setQueryPlanCaptureMaxTimeMillis(long queryPlanCaptureMaxTimeMillis) {
3283    this.queryPlanCaptureMaxTimeMillis = queryPlanCaptureMaxTimeMillis;
3284  }
3285
3286  /**
3287   * Return the max number of query plans captured per request.
3288   */
3289  public int getQueryPlanCaptureMaxCount() {
3290    return queryPlanCaptureMaxCount;
3291  }
3292
3293  /**
3294   * Set the max number of query plans captured per request.
3295   */
3296  public void setQueryPlanCaptureMaxCount(int queryPlanCaptureMaxCount) {
3297    this.queryPlanCaptureMaxCount = queryPlanCaptureMaxCount;
3298  }
3299
3300  /**
3301   * Return the listener used to process captured query plans.
3302   */
3303  public QueryPlanListener getQueryPlanListener() {
3304    return queryPlanListener;
3305  }
3306
3307  /**
3308   * Set the listener used to process captured query plans.
3309   */
3310  public void setQueryPlanListener(QueryPlanListener queryPlanListener) {
3311    this.queryPlanListener = queryPlanListener;
3312  }
3313
3314  /**
3315   * Return true if metrics should be dumped when the server is shutdown.
3316   */
3317  public boolean isDumpMetricsOnShutdown() {
3318    return dumpMetricsOnShutdown;
3319  }
3320
3321  /**
3322   * Set to true if metrics should be dumped when the server is shutdown.
3323   */
3324  public void setDumpMetricsOnShutdown(boolean dumpMetricsOnShutdown) {
3325    this.dumpMetricsOnShutdown = dumpMetricsOnShutdown;
3326  }
3327
3328  /**
3329   * Return the options for dumping metrics.
3330   */
3331  public String getDumpMetricsOptions() {
3332    return dumpMetricsOptions;
3333  }
3334
3335  /**
3336   * Include 'sql' or 'hash' in options such that they are included in the output.
3337   *
3338   * @param dumpMetricsOptions Example "sql,hash", "sql"
3339   */
3340  public void setDumpMetricsOptions(String dumpMetricsOptions) {
3341    this.dumpMetricsOptions = dumpMetricsOptions;
3342  }
3343
3344  /**
3345   * Return true if entity classes should be loaded and registered via ModuleInfoLoader.
3346   * <p>
3347   * When false we either register entity classes via application code or use classpath
3348   * scanning to find and register entity classes.
3349   */
3350  public boolean isAutoLoadModuleInfo() {
3351    return loadModuleInfo && classes.isEmpty();
3352  }
3353
3354  /**
3355   * Set false to turn off automatic registration of entity beans.
3356   * <p>
3357   * When using query beans that also generates a module info class that
3358   * can register the entity bean classes (to avoid classpath scanning).
3359   * This is on by default and setting this to false turns it off.
3360   */
3361  public void setLoadModuleInfo(boolean loadModuleInfo) {
3362    this.loadModuleInfo = loadModuleInfo;
3363  }
3364
3365  public enum UuidVersion {
3366    VERSION4,
3367    VERSION1,
3368    VERSION1RND
3369  }
3370}