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