Summary of changes
A summary of changes needed in migrating to a later version of Ebean.
Upgrading to 17.x from 16.x
Query Changes
The most significant change in Ebean 17.x is the removal of EQL (Ebean Query Language). EQL was a string-based SQL-like query language. This has been removed in favor of more type-safe approaches.
Breaking Change: DB.createQuery(Class, eqlString)
16.x (old way - no longer works in 17.x):
// This NO LONGER WORKS in Ebean 17.x
String eql = "where customer.name like :custName and orderDate > :minOrderDate " +
"order by id desc limit 50";
List<Order> orders = DB.createQuery(Order.class, eql)
.setParameter("custName", "Rob%")
.setParameter("minOrderDate", lastWeek)
.findList();
17.x Solution 1: Query Beans (Recommended)
// Type-safe, IDE auto-completion, compile-time checking
List<Order> orders = new QOrder()
.customer.name.contains("Rob")
.orderDate.greaterThan(lastWeek)
.orderBy().id.desc()
.setMaxRows(50)
.findList();
17.x Solution 2: Standard Query API
// Fluent API with string property names
List<Order> orders = DB.find(Order.class)
.where()
.contains("customer.name", "Rob")
.gt("orderDate", lastWeek)
.order().desc("id")
.setMaxRows(50)
.findList();
17.x Solution 3: Raw SQL (for complex queries)
// For complex database-specific SQL
List<Order> orders = DB.findNative(Order.class,
"select * from or_order o join customer c on c.id = o.customer_id " +
"where c.name like ? and o.order_date > ? " +
"order by o.id desc limit 50")
.setParameter(1, "Rob%")
.setParameter(2, lastWeek)
.findList();
Migration Decision Tree
Do you have an EQL query to migrate?
- Simple predicates (where, order by, limit)?
→ Use Query Beans (recommended) or Standard Query API - Complex SQL (joins, subqueries, functions)?
→ Use Raw SQL / SqlQuery or DtoQuery - Named Queries (@NamedQuery)?
→ Migrate to Query Beans or Standard Query API called directly
EQL Feature Mapping
| EQL Feature | 17.x Replacement | Example |
|---|---|---|
where customer.name like :name |
Query Bean: .name.contains("Rob")Query API: .contains("name", "Rob") |
String pattern matching |
where status = :status |
Query Bean: .status.eq(Status.NEW)Query API: .eq("status", Status.NEW) |
Equality check |
order by id desc, name asc |
Query Bean: .orderBy().id.desc().name.asc()Query API: .order().desc("id").asc("name") |
Result ordering |
limit 50 |
Query Bean: .setMaxRows(50)Query API: .setMaxRows(50) |
Limit results |
fetch customer (name, email) |
Query Bean: .fetch("customer", "name, email")Query API: .fetch("customer", "name, email") |
Eager load specific properties |
Complete EQL to Query Bean Migration Example
EQL (16.x):
String eql = "select (id, name, email) " +
"fetch customer (id, name) " +
"where status = :status and " +
"customer.billingAddress.city like :city " +
"order by id desc " +
"limit 100";
List<Contact> contacts = DB.createQuery(Contact.class, eql)
.setParameter("status", Status.ACTIVE)
.setParameter("city", "Auckland%")
.findList();
Query Beans (17.x - Recommended):
List<Contact> contacts = new QContact()
.select("id, name, email")
.fetch("customer", "id, name")
.status.eq(Status.ACTIVE)
.customer.billingAddress.city.contains("Auckland")
.orderBy().id.desc()
.setMaxRows(100)
.findList();
Other Changes in 17.x
- Named Queries: EQL syntax no longer actively developed (migrate to Query Beans)
- Query Beans: Continue to be the recommended approach for type-safe queries
- Standard Query API: Continues to be supported
- SQL/SqlQuery: Continues to be the best option for complex database-specific queries
Programmatic Database configuration
Prefer explicit programmatic configuration via Database.builder() and injected
Database instances. Older code may still use DatabaseConfig,
DatabaseFactory, ServerConfig, EbeanServerFactory
or rely on implicit bootstrap through DB.
Legacy style:
DatabaseConfig config = new DatabaseConfig();
config.loadFromProperties();
Database database = DatabaseFactory.create(config);
Preferred style:
Database database = Database.builder()
.loadFromProperties()
.build();
For named databases, call .name("mydb") before .loadFromProperties().
Prefer injecting the resulting Database rather than calling DB.byName("...").
Additional Resources
- EQL Documentation - Reference documentation for EQL (16.x)
- Query Beans Documentation - Type-safe query builder
- Where Clause Documentation - Standard Query API predicates
- Release Notes - Detailed changes per version
Upgrading to 12.x from 11.x
-
#1826 Removed
@PrivateOwned, migrate to orphanRemoval=true attribute on@OneToMany - #1824 Stateless updates - Removed update deleteMissingChildren option, instead always use orphanRemoval behaviour change breaking-api
Upgrading to 11.x from 10.x
- #1434 Remove deprecated API from EbeanServer - finder methods that take explicit transaction. Migrate to use ebeanServer.extended()
- #1417 Breaking API - Remove PersistBatch.INSERT ... migrate to PersistBatch.ALL
- #1424 Deprecate / Move ... finder methods that take explicit transaction to ExtendedServer API
- new DbMigration(); -> DbMigration.create();
- findUnique() -> findOne()
- CacheMode.QUERY_ONLY -> GET
- CacheMode.RECACHE -> PUT
- io.ebean.Platform; -> io.ebean.annotation.Platform;
- io.ebean.PersistBatch; -> io.ebean.annotation.PersistBatch;
- io.ebean.TxType; -> io.ebean.annotation.TxType;
- io.ebean.TxIsolation; -> io.ebean.annotation.TxIsolation;
- Remove support for PropertyChangeListener from entity beans
- Remove ServerConfig h2ProductionMode ... means for testing with h2 explicitly set ddlGenerate and ddlRun
Upgrading to 10.x from 9.x
Change package to io.ebean
- Remove DbMigrationConfig.generateOnStart() ... migrate to offline generation
Upgrading to 9.x from 8.x
- Query.includeSoftDeletes() -> setIncludeSoftDeletes()
Upgrading to 8.x from 7.x
- (#682) Remove deprecated Model.Finder constructors that take Id type ... migrate to ones that don't
Upgrading to 7.x from 6.x
- (#352) Remove deprecated API - ValuePair getValue1() getValue2() ... use getNewValue() getOldValue()
- (#344) Remove deprecated annotation @ColumnHstore ... migrate to @DbHstore
- (#343) Remove deprecated interface BeanFinder<T> ... migrate to BeanFindController
- (#342) Remove deprecated method - JsonContext createJsonContext() ... migrate to json()
- (#331) Remove deprecated method - EbeanServer.findVisit() ... migrate to findEach
Changes for: saveAll(), insertAll(), updateAll(), deleteAll()
- (#341) Remove deprecated method - insert(Collection> beans); ... migrate to insertAll()
- (#340) Remove deprecated method - update(Collection> beans) ... migrate to updateAll()
- (#339) Remove deprecated method - save(Collection> beans, Transaction transaction) ... migrate to saveAll()
- (#339) Remove deprecated method - save(Collection> beans, Transaction transaction) ... migrate to saveAll()
- (#338) Remove deprecated method - save(Iterator> it, Transaction transaction) ... please change to iterate yourself and save.
- (#337) Remove deprecated method - delete(Class> beanType, Collection> ids) ... migrate to deleteAll()
- (#336) Remove deprecated method - delete(Iterator> it, Transaction transaction) ... migrate to deleteAll()
- (#335) Remove deprecated method - delete(Collection> beans) ... migrate to deleteAll()
- (#334) Remove deprecated method - delete(Iterator> it) ... migrate to deleteAll()
- (#333) Remove deprecated method - save(Iterator> it) ... change to iterate yourself and save()
- (#332) Remove deprecated method - save(Collection> beans) ... migrate to saveAll(beans)