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

Additional Resources

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)