Default prepared statement cache increased from 100 to 300. This could have the
effect of increased memory consumption for applications traded off with potentially
improved performance due to me cached prepared statements for larger applications.
Note that the Postgres itself has a default of 250.
* Lazy load in pre-delete does not work
* Re-add deleted beans before lazy-load will happen
* Put the contextClear() calls into a finally
This should mean that any beans put into the context would be
cleared even if there was an issue with the loadBean() call.
---------
Co-authored-by: Roland Praml <roland.praml@foconis.de>
* creates support for generics in mapped superclasses
* Changes DeployCreateProperties to allow processing of inheritance hierarchies with generics
* adds tests for ebean-querybean
* bumps querybean-generator version
* fixes tests by changing table names for ProductWithGenericLong and ProductWithGenericString
* Restore format, this reduces the diff
* Restore format, this reduces the diff
---------
Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
* Docs: modify guides README with links to the available guides
* Add TestEntityBuilder for building test entity instances populated by random values
* Improve TestEntityBuilder for emails, BigDecimal precision/scale, protected method allow overriding
* Improve TestEntityBuilder for emails, use PersonOther
This Pull Request aim to fix the problem of DBJSONB dirty detection listed in #3129 which was due to PostgreSQL JSONB key reordering while storing value.
This cause Ebean to mark @DbJsonB properties as dirty on every load (triggering unnecessary UPDATEs and version increments) because the raw DB JSON key order differed from Jackson's serialization order.
Currently, Ebean is using CRC32 Checksum to compare but it is field ordering-dependent.
Introduce JsonContentHash:
A streaming order-independent structural hash of JSON content using Jackson's JsonParser.
Object keys are combined with commutative addition (a + b == b + a) so key ordering does not affect the hash, while array elements use positional hashing to preserve semantic ordering.
The hash uses FNV-1a for strings and MurmurHash3's fmix64 finalizer (both public domain) for mixing, producing a 64-bit hash with strong avalanche properties.
Changes:
- Add JsonContentHash utility (streaming, zero allocation, O(n) time)
- SourceMutableValue: use fast string equality with canonical hash fallback
- ChecksumMutableValue: replace CRC32 with JsonContentHash (also upgrades collision resistance from 2^32 to 2^64)
- No API changes, no schema changes, readSet() untouched
Docker changed and that broke how ebean-test-containers detected the
currently assigned port for a container. That was fixed in 7.18 but
thinking its a good idea to mark that relatively important bug fix
with a bump of the major version to 8.0.
Everyone using ebean-test-containers should consider updating the
ebean-test-containers dependency to 8.0 or 7.18 (both have the fix).
As per https://github.com/ebean-orm/ebean/discussions/3720
```
@Column
ZonedDateTime zonedDateTime2;
```
... resulting in DDL generated as `timestamp(255)`. This is
occurring when the JPA dependency is used like:
jakarta.persistence:jakarta.persistence-api:3.2.0
rather than using the transitive dependency that ebean includes.
Workaround:
Remove the jakarta.persistence:jakarta.persistence-api:3.2.0 dependency.
Fix:
The fix here is to use a timestamp type that has a maximum precision.
When a precision/length is specified greater than the maximum precision
then the fallback type is used which is `timestamp` without any precision.
This change is to reduce PUTs causing cache pollution where
changes that are rolled back are PUT into the bean cache.
Effectively remove the isSkipCacheExplicit() feature and just
use the existing isSkipCache(). This means that skipCacheAfterWrite
is used and PUTs after a database write/insert/update/delete are
effectively skipped.
The change that moved the filterMany predicates to the join had an
issue that extra joins may be needed to support those predicates.
Prior to this change, the extra predicates where effectively just
added to the end of the joins, rather than as a "child" node in
the SqlTreeNode tree.
This fix is in SqlTreeBuilder, where the list of top level extra
joins are first tried to be added as a child to a parent node, and
only if we can't find the parent added at the end.
This is to support the use case where other logic is used to determine if a query
should be "forced" to use the master data source or not, and so it's easier to
pass that as a boolean to the usingMaster() method.
* #3695 Behaviour change: findSingleAttribute() to throw when multiple rows returned by query
On the plus, this makes the behaviour consistent with all the other findOne() methods (ORM, DTO, SqlQuery) and this very much feels like buggy behaviour [to just get the first result and ignore any subsequent results in the ResultSet]
On the negative of merging this bug fix, any application code relying on the existing behaviour with this fix will break and throw a NonUniqueResultException at RUNTIME (not ideal). However, for these cases where the application now throws an exception, people might not be aware that they were relying on this behaviour and this exception could be useful to highlight that (a potential non-deterministic query result was being used and a potential source of bugs was being).
* Change SqlQuery + Mapper + findOne() also to throw NonUniqueResultException
* Problem with filterMany
* Missing id
* Other test
* Fix
* Update TestQueryFilterMany.java
* #3706 Bug fix and change filterMany to put predicates into JOIN clause, Fix for #3626
* Fix tests for Postgres, Oracle, Sql Server
---------
Co-authored-by: Roman Parshikov <promansew@gmail.com>
I think it was a mistake for Ebean to support Class<?> from a security perspective. Instead, Ebean should just use a String <-> Varchar and leave if up to the application to take that String and convert it to a class [and then that potential Class initialisation is owned by the application code and all security considerations around that are owned by the application code].
- Add AggregateFormulaContext with ability to override the default via DatabaseBuilder
- Add group_concat, string_agg, listagg to set of known aggregation functions
* Version 16.1.0
* #3682 @Aggregation is applied to query if entity also has a @Lob column
The underling issue was that Aggregation columns should have been marked as default LAZY. This impact was only hit when @Lob column are included which by default lazy fetched, and that means the default select clause determined.
* Version 16.1.0
* Improve javadoc for Query setUseQueryCache() and unmodifiable
Since 16.x a query using the query cache returns unmodifiable object graphs.
* Update the kotlin-maven-plugin for tests
* Add a profile for EA that excludes kotlin-querybean-generator
* For build workflow use maven profile "default"
To ensure the kotlin-querybean-generator, test modules run
* For build workflow use maven profile "default"
To ensure the kotlin-querybean-generator, test modules run
* #3664 Fix / support for extra JoinColumns on ManyToOne
Allows for extra JoinColumns on ManyToOne. The extra JoinColumn(s) are
expected to be useful for the case of table partitioning where the extra
join column is used to partition the table. In the test case, the partition
column would be the org_id column and common to both tables (same partition key).
* #3664 Fix / support for extra JoinColumns on ManyToOne
Allows for extra JoinColumns on ManyToOne. The extra JoinColumn(s) are
expected to be useful for the case of table partitioning where the extra
join column is used to partition the table. In the test case, the partition
column would be the org_id column and common to both tables (same partition key).
* #3664 Extend test
* #3664 Tidy up test
For FilterMany with QueryBeans, it creates a queryBean to build the filterMany predicates with. This query bean needed 2 changes for this fix:
1. Needs to set it's internal "root" such that it supports chaining (required for or() etc)
2. The ExpressionFactory needs to be explicitly passed to the expression list (rather than get it from the query which is actually null in this case).
* Use autocommit false with findIterate for Postgres
* Use autocommit false with findIterate for Postgres
* Use autocommit false with FindDto queries for Postgres
* Use autocommit false with SqlQuery findIterate queries for Postgres
* Ensure that TransactionFactory.createReadOnlyTransaction() returns an ImplicitReadOnlyTransaction
This change changes TransactionFactoryTenant.createReadOnlyTransaction() to return a ImplicitReadOnlyTransaction, as that is now used to support Postgres use of cursors with findIterate style queries.
warning: No processor claimed any of these annotations: /io.ebean.typequery.TypeQueryBean,/io.ebean.typequery.Generated
This fix is required when the compiler is run with -Werror specified
An alternative workaround is to use compiler arg -Xlint:-processing rather than -Xlint:all
So in a K8s deployment, this adds support for having an initial number of connections to create initially (higher that min connections). This allows for a smoother deployment, by effectively having initially more connections than min in order to immediately take production load, and then over time trim back down towards the min connections.
So in k8s I am setting min, initial and max connections, where initial connections is high enough to take full production load straight after readiness true.
* fix jackson NCDF error
split jackson SPI impl into it's own module
* Restore format
* Restore format
* Trim up dependencies
* Rename module to ebean-core-json
---------
Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
It barfs trying to parse the 25-EA version, means the kotlin-querybean-generator fails the build for the Java Early Release versions.
With this, it will skip the kotlin modules for the Java Early Access release builds.
Note that this still supports Java 11.
The 10.0 version of ebean-datasource uses Multi-Version jar such that if running using Java 21+ then it will use Virtual Threads for the background Heartbeat validation and also background closing of connections.
The `@Column` length defaults to 0 rather than 255, this allows us to detect when it has been explicitly set and thus for Postgres we can now have:
@Column(length=255) mapping to -> varchar(255)
@Column mapping to -> varchar
@MappedSuperclass was excluded from the generated reflect-config.json, this PR fixes that.
The missing reflect-config entry for MappedSuperclass means that with native-image the @Id property isn't found when its on a MappedSuperclass, and that ended up as a NPE in BeanPropertyAssocOne.
e.g. DatabaseBuilder.queryPlanExplain("explain (verbose)")
Also changes Postgres default explain to be:
explain (analyze, costs, verbose, buffers, format json)
Prior to this change they made an explicit transaction if one was needed, and this would always use the Main DataSource.
With this change, when there is no transaction assigned to the query and no active transaction, then the find future query will use the ReadOnly DataSource if it has been configured (e.g. ReadOnly DataSource might point to a read replica database instance).
Entities without *any* relationships can support "sharable instances" with bean caching. This change restores that and uses unmodifiable instances (rather than the old ReadOnly).
Currently, for a query to get shared instances it now needs to explicitly use setUnmodifiable(true) where as before it defaulted to shared instances so that is a behaviour change.
Additionally, bean cache queries were not honouring setUnmodifiable(true) and with these changes they now do.
- Query Cache now holds unmodifiable collections
- Can no longer have readOnly=false with queryCache=true
- Reference beans now also honor unmodifiable
- Effectively no longer does bean cache lookup for reference beans (which it defaulted to when cacheSharableBeans true, e.g. Country entity bean)
Die to Quarkus dev mode (#3541#3582) we want to log FilerException at WARN level rather than ERROR. This is because Quarkus dev mode will invoke the annotation processor more than usual, so we expect to fail with the FilerException.
The test was using field access??? when that isn't valid unless we specifically turn on enhancement to support that.
Using proper method access though stops the test from failing.
It seems like mysqldump just adds ;; to the last line and does not
check if that line is a comment. To work around that it's good enough
to move the comment one line up - as long as the END does not end with ;
(which here it does not so that is ok)
ebean-test-containers version 7.6 supports extraDb for MySql and MariaDb, resolving #3511 with extraDb configuration for each extra schema/database required with MySql or MariaDb.
So we can no longer dynamically change the Clock being used and instead for testing purposes need to create the Database with a test clock instance as needed.
Refer to the ExtendedServerTest for an example
- Adds new exceptions UnloadedPropertyException and UnmodifiableEntityException
- Change InterceptReadOnly to use these exception instead of IllegalStateException
- Change collections BeanSet, BeanList, BeanMap from using IllegalStateException to UnsupportedOperationException [to bring these in line with JDK unmodifiable collections]
* ADD: Testcase for showing nested transaction with batch-mode not flushing batch on commit
* Update test only - TestNestedTransaction.test_txn_nestedWithInnerBatch()
Update the test to show that we desire the nested transaction changes to be "visible" after a commit regardless of flushOnQuery etc
* #3564 Fix for nested transaction with batch-mode does not flush
- Adds flush() into ScopeTrans.commitTransaction()
- Related fixes in DefaultServer execute() and executeCall() where it was performing extra unnecessary nesting on PersistenceException
* Touch
---------
Co-authored-by: Jonas Pöhler <jonas.poehler@foconis.de>
As HelpScopeTrans isn't in an exported package it's use fails with an error in module path. This adds AOPTransactionScope in the exported package io.ebean.plugin and moves the required methods from SpiEbeanServer to SpiServer to support this move.
This also requires an associate change in ebean-agent to support this feature which will be in ebean-agent 14.9.0.
Internally in CQueryBuilder only use query.setSelectId(); for findCount when the entity bean has a @Id property [which it doesn't strictly need and likely won't have for view based entities]
Brings the kotlin-querybean-generator up to date with the [java] querybean-generator in terms of how it has specific "associated beans" for ToOne and ToMany type relationships
* #3552 Column alias required for SQL Server + findCount + distinct
- Modifies CQueryBuilder with the main fix which is to use the database platform selectCountWithColumnAlias for all distinct queries [and later disable it for single column case]
- Modifies SqlTreeBuilder because we need to NOT use the column alias for the count distinct SINGLE COLUMN case. So change here to:
- build the root SqlTreeNode first as part of constructor
- use rootNode.isSingleProperty() to NOT use column alias for the single column case
- Hence need to initialise DefaultDbSqlContext AFTER the root SqlTreeNode
- Modifies DefaultDbSqlContext with no effective change, just columnIndex++ ONLY when we are actually using column alias
- Modifies H2Platform to also use selectCountWithColumnAlias true
* #3552 selectCountWithColumnAlias true for MariaDB and MySql
Plus fix TestRowCount for Oracle platform
This change is a simplification such that these batch attributes are always stored and restored for nested ScopeTrans.
There are no expensive side effects of doing it this way.
This fixes issues where the batch attributes are changed after the ScopeTrans is created (like the test for this PR).
Although this is ok, makes me think that another option is just to have query.setReadOnly(true)
to mean ... readOnly + disableLazyLoad + error reading unloaded property or collection. As in,
readOnly true without these extra things does not that good [as in the existing readOnly does
not seem very good/safe/useful to use].
Currently, the SELF response type of QueryBuilder returns as Object when really we want it to return the SELF generic type of QueryBuilder, QueryBean, IQueryBean etc
Note that this change requires an updated ebean-agent
Paging is an alternative to specifying the maxRows + firstRow + orderBy on a query.
Example:
```java
var orderBy = OrderBy.of("lastName desc nulls first, firstName asc");
var paging = Paging.of(0, 100, orderBy);
DB.find(Contact.class)
.setPaging(paging)
.where().startsWith("lastName", "foo")
.findList();
```
Changes the query bean code generation for "Associated beans" to have separate AssocOne and AssocMany for *ToOne and *ToMany relationships.
Moves the filterMany() expressions such that they are only available on the *ToMany relationships.
Internally in OrmQueryDetail.markQueryJoins() the SpiQueryManyJoin is determined and returned. This change uses this and effectively removes the code from OrmQueryRequest.determineMany() and BeanDescriptor.manyProperty() which was the source of this issue (performing a similar task but not correctly taking the full path into account and hence the source of this bug).
* ebean-test: Modify postgis platform to support both net.postgis and org.postgis
Use Class.forName() to test existence of net.postgis.jdbc.DriverWrapperLW and if available use that driver rather than the older org.postgis.DriverWrapperLW one.
Also support explicitly specifying the driver to use via test property - ebean.test.postgis.driver
* Update test for net postgis to use a separate container
* Remove NetPostgisSetup as PostgisSetup handles both cases now
* Added modules `ebean-net-postgis-types`, `ebean-net-postgis` for new `net.postgis` geometry types without support for GeoLatte.
* Added missing `uses` entry in `module-info.java` for `io.ebean.api`.
* Bump ebean-datasource dependency to 9.0 with automatic Lambda mode detection
ebean-datasource 9.0 automatically detects when it is running in AWS Lambda
and will set validateOnHeartbeat to false. In Lambda we don't want to validate
connections in background threads that can suspend in Lambda.
ebean-migration 14.1.0 defaults fastMode to true. This means that it first
runs a fast check that all migrations have been run. If that does not succeed
for any reason it runs the normal migration process.
Bugfix for "Long/slow transaction reaper" in Wildfire that can close/rollback a transaction in a different thread. Fix is to use active flag to inactivate the transaction and detect that case in JtaTransactionManager.getCurrentTransaction()
* Bump parent pom to 4.2 with EA changes to annotation processing
Annotation processing needs to be explicitly on in JDK 24 EA builds
* Bump bytebuddy version in ebean-test and use experimental=true for EA builds
* Use parent pom 4.3 with bytebuddy.experimental=true by default for surefire
We want to rename TQRootBean to QueryBean. I can't do that right now because we need to make ebean-agent aware of that first. So yes, perhaps not ideal with IQueryBean but I think it will make sense once TQRootBean is renamed to QueryBean.
Adding this means that it will work with an old ebean-agent. It takes a few days to get a new IntelliJ plugin released and we can't wait due to wanting to release the bug fix for #3381
14.0.0 via #3295 introduced this bug.
#3295 introduced a behaviour where bulk updates clear the persistence context. Now the lazy loading of a BeanCollection works with an assumption that the "parent bean" is in the persistence context (and this assumption is broken with that change for this test case). That is, the bulk update is clearing the persistence context - removing the parent bean BEFORE the lazy loading is invoked ... and that doesn't then work because the parent bean isn't in the persistence context.
This fix means that when lazy loading many's, the parent beans are putIfAbsent into the persistence context.
* #3370 LimitOffsetPagedList add getTotalCount cache
* Move totalRowCount check to inside the lock
* No change, format only on LimitOffsetPagedList
---------
Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
Note that this only works for Multi-Tenant PARTITION mode where the TenantId is a column on the tables (rather than schema or database multi-tenancy mode).
- changes SqlQueryEvent into an interface.
- captures the bind values the slow query used and makes those available via SlowQueryEvent
- also makes the query label and profileLocation available via SlowQueryEvent
That is, previously the relationship back from the child to the parent was being updated when the child bean was new or dirty BUT NOT in the case when the child bean was loaded and unchanged.
This fix includes that case updating the ManyToOne side of the relationship on the child when the save is cascaded.
* feat: Add query.setHint() to support sql hint as inline comment in select queries
This is for ORM queries only.
An ORM query like:
new QCustomer()
.setHint("FirstRows")
.select(QCustomer.Alias.id, QCustomer.Alias.name)
.findList();
Produces SQL that includes the hint as an inline comment like:
select /*+ FirstRows */ t0.id, t0.name
from customer t0
* Fix test QOrderTest
* feat: Add includeLabelInSql configuration option to include query label as inline comment in generated sql select
The generated select queries can look like:
select /* MyInnerTest.insert_and_find */ t0.id, ...
Using either query.setLabel() or profile location (which all query beans get by default). This means that tooling looking at sql in the database can more easily relate that sql back to application code.
* More tests for labels with includeLabelInSql=true
* Remove trim when using profileLocation label
This provides a simpler DbExpressionRequest interface for db platform specific expression adapters (rather than the SpiExpressionRequest which has more features that we don't wish to expose to those expression adapters.
- Use 4000 to match the DB2 logic for considering a column a lob (for distinct etc)
- Rename distinctNoLobs -> platformDistinctNoLobs
- Rename isDbLob() -> isLobForPlatform()
- Rename unselectLobs() -> unselectLobsForPlatform()
This version of avaje-config supports using AWS AppConfig as a configuration source (via avaje-aws-appconfig). It also supports dynamic changing Logback logging levels (via avaje-dynamic-logback).
This adds the option to register a JVM shutdown hook (which we generally will not use with ebean as the ebean io.ebean.Database shutdown wants to shutdown the DataSource after any background tasks have completed).
This also adds an experimental feature for use with AWS Lambda to check for old idle connections due to lambda suspension.
commit 20152e16891582f8ff466a93ec2cf01871824d6d
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date: Tue Feb 27 20:59:51 2024 +1300
#3341 Update DatabaseConfig for fluid style + javadoc
commit 1c495a7384
Author: Roland Praml <roland.praml@foconis.de>
Date: Mon Feb 26 10:25:42 2024 +0100
Fix: Compile errors
commit 574876b758
Merge: df7b0487777634fc3e
Author: Roland Praml <roland.praml@foconis.de>
Date: Fri Feb 23 16:16:39 2024 +0100
Merge branch 'master-rob' into FOCONIS-string-length-validation
commit df7b04877d
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date: Mon Jun 26 21:16:32 2023 +1200
#3121 BindMaxLength validation
At deploy time derive a BindMaxLength property to use
per BeanProperty
commit 4683877e0b
Merge: 9a4b9d4bed0020ab8c
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date: Fri Jun 23 16:51:34 2023 +1200
Merge branch 'string-length-validation' of github.com:FOCONIS/ebean into FOCONIS-string-length-validation
commit d0020ab8ce
Author: Roland Praml <roland.praml@foconis.de>
Date: Tue Jun 20 14:47:20 2023 +0200
Length validation less invasive
commit 9b3b8ad46a
Author: Roland Praml <roland.praml@foconis.de>
Date: Tue Jun 20 13:03:04 2023 +0200
extended DataBind, so that it could return the last bound object
commit ca3c02bc1c
Author: Roland Praml <roland.praml@foconis.de>
Date: Mon Jun 19 09:52:52 2023 +0200
Failing test for SqlServer
This is the batch size used with PreparedStatement executeBatch() with
batched inserts, updates and deletes. 20 is really on the low side and
bumping this default to 100 seems good and right.
The issue fixed here is a timing one where the parent bean is being updated.
The updated parent bean has its internal state reset before the cascade down
to the SaveManyBeans where for this case it needs to identify is the 'vanilla'
collection has set (via setChildren(new ArrayList()).
This fix is a change that for updated beans the dirtyProperties is always obtained
and then use this for the isChangedProperty() check.
- Reuse the existing OmBeanListParent and child
- Simplify the test setup code
- Rename test methods to maybe better reflect what I think is failing
Noting that markAsDirty doesn't specifically have anything to do with this bug but it's more on whether the parent bean is dirty or dirty (markAsDirty is just a way to make the parent bean dirty).
This change is that findFutureCount, findFutureList, findFutureIds do not trigger a flush on BatchedPstmtHolder.
This is to address the possible ConcurrentModificationException that could occur at BatchedPstmtHolder.closeStatements(BatchedPstmtHolder.java:153)
Using SqlUpdate or an ORM Update query clear the appropriate part of
the PersistenceContext. The effect is that ORM queries executed after
a bulk update will effectively load a fresh copy of the data from the
database and will not reuse an instance from the persistence context
if the bean in question had already been loaded.
If there is an entity bean short name clash like PString, PLong, etc then
fully qualify all the property types in the generated code, otherwise use
imports for the property types.
When using DatabaseBuilder.readOnlyDatabase(true) then
ebean will:
- Set the DataSourceBuilder to use autoCommit=true and readOnly=true
- Use the same DataSource instance for both dataSource and readOnlyDataSource
This is to simplify the setup/configuration for creating a Database that
will only have read-only use.
Note that readOnly=true is a JDBC hint and for example H2 database effectively
ignores that hint where as Postgres will enforce the read-only true nature.
That is, existing code using DataSourceConfig has access to the getter
methods of DataSourceConfig. The DataSourceBuilder interface only has
the setter methods and DataSourceBuilder.Settings has both getters and
setter methods.
That is, the refactor to extract the DataSourceBuilder interface also
split off the getter methods to the DataSourceBuilder.Settings interface
(because most of the time when using the builder we only need the
setter methods and effectively hiding the getter methods behind the settings()
is useful to simplify the API for users).
So DatabaseBuilder.Settings has all the getters for code looking to read
the configuration that has been set. So DatabaseBuilder now just has the
setter methods.
Use DatabaseBuilder.settings() to access the settings and read the config
that has been set.
First step in migrating the ebean-datasource API to use builder pattern.
DataSourceConfig (concrete type) migrating to DataSourceBuilder (interface).
A followup step will deprecate the use of DataSourceConfig.
The loadMode ends up as a suffix to some query metrics.
For example "foo.findIt_baz(+lazy)", and the (+lazy) part isn't safe/friendly to tools
like Grafana. So change to instead of (+lazy) use __lazy.
JDK 22 changes such that annotation processors are not found by default on
the classpath. As such they either need to be explicitly registered with
the compiler (e.g. maven-compiler-plugin) or use -proc:full
With this, people can depend on ebean-postgis (the composite) and get all the
dependencies they need (which is ebean-platform-postgres + ebean-postgis-types
+ others).
This should just make it easier for people in that currently we need both
ebean-postgis + ebean-postgres which isn't obvious enough.
The fix is for LoadManyRequest to detect when a MapKey is on the collection
and include that in the lazy loading query (to avoid the N queries invoked)
This shows the extra lazy loading that is occurring when clear() is
called on the [Bean]Set DUE to the hashcode/equals implementation that
is present on the entity bean that is in the Set.
- The error reported was that a DataSource connection pool maxed out
- The symptom was that there was an additional lazy loading queries invoked via the hashCode/equals implementation of ManyToMany Set.
- The fix is for BeanSet init() to lazy load with onlyIds = false, that avoids the extra lazy loading query from being executed
Originally the API took explicit transactions but then the API changed
toward query.usingTransaction(), which means the SpiQuery holds the
explicit transaction.
This change is to update the SpiEbeanServer API to reflect that it can get
explicit transaction from SpiQuery.transaction() rather than pass transaction
around.
Doing this also identified a small bug where L2 cache could be hit when it should
not after there is some update on the transaction (hence the adjustment to the
test TestBeanCache missCount)
The filterMany( <string expressions> ) uses the language parser which
ultimately will we probably remove in ebean 15.x
Code can migrate to filterManyRaw() instead or better yet change to
use the improved query beans filterMany( <closure> ) option that will
be included in this same ebean release.
Fix for the case where the filterMany is not executed on a separate
query but instead part of the origin query.
The fix is to use the appropriate DeployParser and also fix the path
alias like ${} -> ${contacts}
Fix for the case where the filterMany is not executed on a separate
query but instead part of the origin query.
The fix is to use the appropriate DeployParser and also fix the path
alias like ${} -> ${contacts}
Query beans also generate a "Assoc" query bean that is used
for the relationships. Previously these were generated into a
.query.assoc package and with this they are generated as an
inner class of the query bean.
This then allows the change where an additional filterMany()
is generated on the "Assoc" bean that takes a closure. This
simplifies the use of query beans for filterMany.
This change to the generated query beans needs a change to the
ebean-agent enhancement.
- Don't cache ebean compiled query plan when InTuples goes into literal mode
- Postgres maxInBinding = 32_000;
- SQLite maxInBinding = 800;
- Note that not caching the compiled query plan means that metrics visitor isn't
going to see it, we lose collection of that query execution metric. We might
need a plan to fix this later.
So as to not exceed the limit on bind values, the InTuples expression can
go into literal mode where it uses literal values for supported types -
Numbers, Strings, UUID, and LocalDate.
The MultiValue binding that we use for Postgres, Yugabyte etc was lost with
the changes in #3133 and this puts that back.
We desire to use Postgres ANY Array binding for these cases.
H2Database 2.x changed KEY and VALUE to be deemed keywords for SQL compliance. This is actually a bit of a pain as all the other databases we test allow KEY and VALUE as column names.
This changes the setup for H2Database to treat KEY and VALUE as non keywords as before and be more consistent with the other databases.
Originally, ImplicitReadOnlyTransaction was built to support read-only DataSource where the connections are using autoCommit true. This change modified ImplicitReadOnlyTransaction to also support use with the main DataSource where the connection are not using autoCommit true.
This is also now needed for the query.usingMaster() case where we have an implicit read only transaction but use the main DataSource with underlying connection requiring explicit commit() at the end of the transaction.
When we have a read replica with potential for replication lag, and config a read only DataSource to use that read replica, by default a query executed without a current transaction will use the read replica.
We specify usingMaster() when we explicitly want to execute a query and use the master data source.
@@ -30,7 +30,6 @@ The ID type (IDENTITY, SEQUENCE, GENERATOR, EXTERNAL)
`dbmigration.platform.<PLATFORM>.mapping`
Adjust the mapping. For example `BOOLEAN=integer(32);BIT=tinyint(3)`
`ebean.migration.applyPrefix`
Set this to "V" to be compatible with FlywayDB.
@@ -50,7 +49,7 @@ Set to true if the DB migration should be generated on server start.
The version of a pending drop that should be generated as the next migration.
`ebean.migration.includeGeneratedFileComment`
TODO
Adds the header about the migration files being generated when true. Reading 'THIS IS A GENERATED FILE - DO NOT MODIFY'
`ebean.migration.metaTable`
For running migration the DB table that holds migration execution status. Default 'db_migration'
@@ -65,17 +64,17 @@ Subdirectory the model xml files go into. Default 'model'
Suffix. Default '.model.xml'
`ebean.migration.name`
Description text that can be appended to the version to become the ddl script file name
Description text that can be appended to the version to become the ddl script file name.
`ebean.migration.patchInsertOn`
migration versions that should be added to history without running.
Migration versions that should be added to history without running.
`ebean.migration.patchResetChecksumOn`
migration versions that should have their checksum reset and not run.
Use this if you get a 'Checksum mismatch' error.
`ebean.migration.placeholders`
A comma and equals delimited placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
A comma and equals delimited map of placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
`ebean.migration.platform`
The database platform to generate migration DDL for.
@@ -90,7 +89,7 @@ The migration version name (typically FlywayDb compatible). Example: 1.1.1_2
### Ebean UUID options
`ebean.uuidVersion`
Controls, how the UUIDs are generated. Possible values
Controls how the UUIDs are generated. Possible values:
- VERSION4 (default) generate random V4 UUIDs,
- VERSION1 generate rfc4122 compliant Type 1 UUIDs (requires a state file)
- VERSION1RND generate fake Type 1 UUIDs
@@ -98,7 +97,7 @@ Controls, how the UUIDs are generated. Possible values
Note, that V1 UUIDs in conjunction with AUTO_BINARY_OPTIMIZED will give you the best index performance, but you MUST understand how this works to avoid collisions.
`ebean.uuidStateFile`
The state file that is Required to generate V1 UUIDs
The state file that is required to generate V1 UUIDs.
### DocStoreConfig
@@ -107,7 +106,7 @@ The state file that is Required to generate V1 UUIDs
True when the Document store integration is active/on.
`ebean.docstore.allowAllCertificates`
Set to true such that the client allows connections to invalid/selfsigned SSL certificates.
Set to true such that the client allows connections to invalid/self-signed SSL certificates.
`ebean.docstore.bulkBatchSize`
The default batch size to use for the Bulk API calls.
@@ -192,7 +191,7 @@ Suffix appended to the base table to derive the view that contains the union of
Set to true if the DataSource uses autoCommit. Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
`ebean.autoReadOnlyDataSource`
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig.
[](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
Step-by-step guides written as instructions for AI agents and developers.
## Adding Ebean ORM with PostgreSQL to an existing Maven project
A three-part guide covering everything needed to wire Ebean + PostgreSQL into an
existing Maven project. Complete the steps in order.
| Step | Guide | Description |
|------|-------|-------------|
| 1 | [Maven POM setup](add-ebean-postgres-maven-pom.md) | Add Ebean dependencies, the enhancement plugin, and the querybean-generator annotation processor to `pom.xml` |
| 2 | [Database configuration](add-ebean-postgres-database-config.md) | Configure the Ebean `Database` bean using `DataSourceBuilder` and `DatabaseBuilder` with Avaje Inject |
| 3 | [Test container setup](add-ebean-postgres-test-container.md) | Start a PostgreSQL (or PostGIS) Docker container for tests using `@TestScope @Factory` with Avaje Inject; covers image mirror, read-only datasource, and PostGIS variant |
## Entity beans
| Guide | Description |
|-------|-------------|
| [Lombok with Ebean entity beans](lombok-with-ebean-entity-beans.md) | Which Lombok annotations to use and avoid on entity beans; why `@Data` is incompatible with Ebean; how to use `@Getter` + `@Setter` + `@Accessors(chain = true)` |
## Database migrations
| Guide | Description |
|-------|-------------|
| [DB migration generation](add-ebean-db-migration-generation.md) | Add `GenerateDbMigration.java` to generate schema diff migrations offline; configure the migration runner; understand `.sql` and `.model.xml` output files; workflow for pending drops |
## Connection Pooling & DataSource Configuration
The [ebean-datasource](https://github.com/ebean-orm/ebean-datasource) project provides
comprehensive guides on connection pool configuration and best practices. These are particularly
useful for production deployments, especially in Kubernetes or AWS environments:
| Guide | Description |
|-------|-------------|
| [Creating DataSource Pools](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/create-datasource-pool.md) | Step-by-step guide for basic, read-only, Kubernetes, and AWS Lambda datasource configurations |
| [AWS Aurora Read-Write Split](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/aws-aurora-read-write-split.md) | Setting up dual DataSources with Aurora read and write endpoints for Ebean integration |
| [Connection Validation Best Practices](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/connection-validation-best-practices.md) | Understanding connection heartbeat strategies and why `Connection.isValid()` is the recommended approach |
---
## Helping AI agents find these guides
AI coding agents can only follow these guides if they know they exist. Below are
copy-paste snippets for the most common AI tooling configurations. Add whichever
applies to your project.
### Project `README.md` (universal — works with all AI tools)
Add a section near the top of your project README:
```markdown
## AI Agent Instructions
This project uses [Ebean ORM](https://ebean.io). Step-by-step guides for common
Ebean tasks (Maven setup, database configuration, test containers, DB migrations,
To generate migrations for multiple platforms simultaneously, use `addPlatform()`
instead of `setPlatform()`:
```java
migration.addPlatform(Platform.POSTGRES);
migration.addPlatform(Platform.SQLSERVER17);
migration.addPlatform(Platform.MYSQL);
```
Each platform gets its own subdirectory under `dbmigration/`.
### Include index
When enabled the migration generation also generates a file that contains
all the migrations and their associated hashes. This is a performance
optimisation (that will become the default) and means that the migration
runner just needs to read the one resource and has the pre-computed hash
values (so does not need to read each migration resource and compute the
hash for each of those at runtime).
```java
migration.setIncludeIndex(true);
```
### Strict mode
Strict mode (on by default) errors if there are any pending drops not yet applied.
Set to `false` to allow generation to proceed regardless:
```java
migration.setStrictMode(false);
```
### Applying pending drops
Destructive changes (drop column, drop table) are **not** included in the apply
SQL by default — they are recorded as `pendingDrops` in the model XML. This allows
the application to be deployed without immediately dropping columns (important for
rolling deployments).
The migration runner logs a message when pending drops exist:
```
INFO DbMigration - Pending un-applied drops in versions [1.1]
```
When ready to apply the drops, set `setGeneratePendingDrop` to the version that
contains the pending drops:
```java
migration.setVersion("1.3");
migration.setName("drop-pending-from-1.1");
migration.setGeneratePendingDrop("1.1"); // apply drops recorded in version 1.1
migration.generateMigration();
```
### Custom dbSchema
If the project uses a named Postgres schema (set via `ebean.dbSchema` in
`application.properties`), no additional configuration is needed in
`GenerateDbMigration` — Ebean picks up the schema from the application config
automatically when running in offline mode.
```properties
# application.properties
ebean.dbSchema=myschema
```
---
## Troubleshooting
| Symptom | Likely cause | Fix |
|---------|-------------|-----|
| `no changes detected - no migration written` | Entity beans unchanged since last migration | Make entity bean changes first, then re-run |
| `DbMigration - Pending un-applied drops` | A previous migration has drops not yet applied | Either suppress with `setStrictMode(false)` or apply drops with `setGeneratePendingDrop(...)` |
| Generated SQL is empty or wrong | Wrong working directory path | Set `setPathToResources(...)` to the correct module-relative path |
| `ClassNotFoundException` for entity classes | Test classpath not including main classes | Ensure `exec.classpathScope=test` or run via IDE with test classpath |
| Migrations not running on startup | Property key wrong or `ebean-migration` missing | Verify `ebean[.name].migration.run=true` and that `ebean-migration` is on the classpath |
See the DB migration generation guide (`add-ebean-db-migration-generation.md`) for
full details on generating and managing migration files.
---
## See Also
For advanced connection pool configuration, production deployment patterns, and connection
validation best practices, see the [ebean-datasource guides](https://github.com/ebean-orm/ebean-datasource/tree/master/docs/guides/):
- **[Creating DataSource Pools](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/create-datasource-pool.md)** — Covers read-only pools (`readOnly(true)` + `autoCommit(true)`), Kubernetes deployment strategies using `initialConnections`, and AWS Lambda optimization
- **[AWS Aurora Read-Write Split](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/aws-aurora-read-write-split.md)** — Setting up dual DataSources with Aurora reader and writer endpoints, including Ebean secondary datasource routing
- **[Connection Validation Best Practices](https://github.com/ebean-orm/ebean-datasource/blob/master/docs/guides/connection-validation-best-practices.md)** — Why `Connection.isValid()` is the recommended default and when (rarely) explicit `heartbeatSql` is needed
---
## Verification
1. Start the application (or run `mvn test -pl <your-module>`).
2. Look for log output similar to:
```
INFO o.a.datasource.pool.ConnectionPool - DataSourcePool [db] autoCommit[false] min[1] max[5]
INFO io.ebean.internal.DefaultContainer - DatabasePlatform name:db platform:postgres
```
3. If you see `DataSourcePool` and `DatabasePlatform` log lines, Ebean is connected and
| `@Data` | ❌ Avoid | Includes `@EqualsAndHashCode` and `@ToString` — both problematic |
| `@Value` | ❌ Avoid | Makes fields final — incompatible with Ebean's field-level bytecode enhancement |
| `@Accessors(fluent = true)` | ✅ Safe | Removes `get`/`set` prefix — Ebean does not require JavaBeans naming conventions and works with any accessor style |
| `@Builder` | ⚠️ Careful | Usable on non-entity helper/factory classes; on entity beans it requires a no-arg constructor alongside it and offers no advantage over `@Accessors(chain = true)` |
---
## Relationship with Ebean Bytecode Enhancement
Ebean's bytecode enhancement (applied by `ebean-maven-plugin` at build time) modifies
the `setXxx()` methods of entity beans to:
1. Mark the field as dirty (changed) so only modified fields are included in UPDATE statements
2. Support lazy loading of associations when a getter is called on an unloaded field
For this to work correctly, Ebean needs:
- Accessor methods for each persistent field (any naming style is fine — `getFoo()`, `foo()`, or no accessors at all; Ebean can also access fields directly)
- No override of `hashCode()` / `equals()` that would interfere with the identity map — which means **no `@Data` or `@EqualsAndHashCode`**
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.