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