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