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