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