Ebean Query Language (EQL)

⚠️ Ebean 16.x only: Ebean Query Language (EQL) was removed in Ebean 17.x. If you are using Ebean 17.x, use Query Beans (recommended) or the standard Query API instead. See Upgrading from 16.x to 17.x for migration examples.

Overview

Ebean Query Language (EQL) was a SQL-like query language available in Ebean 16.x releases that allowed you to write queries using a string-based syntax similar to SQL. EQL queries were parsed early and converted to type-safe Query objects that could be further modified before execution.

EQL has been removed in Ebean 17.x in favor of more type-safe approaches using Query Beans (recommended) and the standard Query API.

EQL Syntax (16.x reference)

This section documents EQL syntax for reference if you are maintaining an Ebean 16.x application.

Basic Structure

EQL queries followed this basic pattern:


find [selected-properties]
[fetch property-paths]
where [predicates]
order by [order-by-clause]
limit [limit-clause]

Complete Example (16.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();
  

WHERE Clause

The where clause contained predicates using property paths:


"where customer.name like :custName"           // string comparison
"where status = :status"                       // property equals
"where orderDate > :date"                      // date comparison
"where amount between :min and :max"           // range check
"where customer.id in :customerIds"            // IN clause
"where items.size > 0"                         // collection check
  

ORDER BY Clause


"order by id"                    // ascending
"order by id desc"               // descending
"order by customer.id, id desc"  // multiple properties
  

SELECT and FETCH


// Select specific properties from root entity
"select (name, email) where status = :status"

// Fetch properties from related entities
"fetch customer (id, name) where status = :status"
"fetch customer.address (city, country) fetch items where ..."

// Named query definition
@NamedQuery(
  name="bugStatus",
  query="fetch loggedBugs where loggedBugs.status = :bugStatus order by name"
)
  

Why EQL Was Removed

  • Lack of type safety: Query strings are error-prone and can only be validated at runtime
  • No IDE support: String-based syntax does not benefit from IDE auto-completion or refactoring
  • Maintenance burden: Maintaining a custom query parser was resource-intensive
  • Better alternatives: Query Beans provide the same functionality with compile-time safety
  • Industry trend: Modern ORMs favor type-safe query builders

Migrating from EQL to 17.x

See Upgrading from 16.x to 17.x for detailed migration examples converting EQL queries to:

  • Query Beans (Recommended) - Type-safe, compile-time checking, IDE auto-completion
  • Standard Query API - Fluent API using method calls
  • Raw SQL / SqlQuery - For complex database-specific queries

Quick Migration Example

EQL (16.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();
  

Query Beans (17.x - Recommended):


List<Order> orders = new QOrder()
  .customer.name.contains("Rob")
  .orderDate.greaterThan(lastWeek)
  .orderBy().id.desc()
  .setMaxRows(50)
  .findList();
  

Standard Query API (17.x - Alternative):


List<Order> orders = DB.find(Order.class)
  .where()
    .contains("customer.name", "Rob")
    .gt("orderDate", lastWeek)
  .order().desc("id")
  .setMaxRows(50)
  .findList();
  

Named Queries (16.x)

Named Queries in Ebean 16.x used EQL syntax defined in @NamedQuery annotations. In Ebean 17.x, Named Queries still exist but the EQL syntax within them is no longer actively used.

16.x Named Query Definition:


@NamedQueries(value={
  @NamedQuery(
    name="bugsSummary",
    query="find (name, email) fetch loggedBugs (title, status) where id=:id "),
  @NamedQuery(
    name="bugStatus",
    query="fetch loggedBugs where loggedBugs.status = :bugStatus order by name")
})
@Entity
public class User {
  ...
}
  

16.x Named Query Execution:


User user = DB.createNamedQuery(User.class, "bugsSummary")
  .setParameter("id", 1)
  .findOne();
  

17.x Alternative: Use Query Beans or standard Query API directly instead of Named Queries.

Resources

Troubleshooting

Q: I see "DB.createQuery() no longer accepts an EQL query string" error

A: You are using Ebean 17.x which removed EQL support. The method DB.createQuery(Class, eqlString) no longer exists. Use one of these alternatives:

  1. Query Beans (recommended): new QCustomer().name.eq("Rob").findOne()
  2. Standard Query API: DB.find(Customer.class).where().eq("name", "Rob").findOne()
  3. Raw SQL: DB.findNative(Customer.class, sqlString)

Q: Can I still use Ebean 16.x with EQL?

A: Yes, Ebean 16.x continues to receive maintenance updates. See releases for available 16.x versions.

Q: Where can I find more migration help?

A: See the Upgrading from 16.x to 17.x guide for detailed examples and migration strategies.