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