Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.

public final class Query<T>

  1. Object
  2. Query

A query named in the entity’s own terms.

List<Note> recent = notes.query()
        .eq("author", author)
        .gt("created", cutoff)
        .orderBy("created", false)
        .limit(20)
        .list();

Every name here is a JAVA FIELD of the entity, which is what makes the query portable: the builder maps it to the column the entity declared and quotes it for the engine, so a field called createdAt works on PostgreSQL, which folds an unquoted name to lower case, exactly as it works on the other two. A name that is not a field of this entity is refused immediately, naming the ones that are, rather than reaching the server as a column it does not have.

Values are bound, never interpolated. A Date becomes epoch milliseconds and a boolean becomes 0 or 1, which is how an entity stores them, so what the query compares is what the table holds.

Conditions are joined with AND, in the order they were added. OR and grouping are deliberately absent: the moment a query needs them it is past what naming fields expresses clearly, and Dao.find takes the SQL that says it.

Methods

public Query<T> eq(String field, Object value)field = value, or field IS NULL when the value is null.
public Query<T> ne(String field, Object value)field <> value, or field IS NOT NULL when the value is null.
public Query<T> gt(String field, Object value)field > value.
public Query<T> gte(String field, Object value)field >= value.
public Query<T> lt(String field, Object value)field < value.
public Query<T> lte(String field, Object value)field <= value.
public Query<T> like(String field, String pattern)field LIKE pattern, with the engine’s own wildcards: % for any run of characters and _ for one.
public Query<T> isNull(String field)field IS NULL.
public Query<T> isNotNull(String field)field IS NOT NULL.
public Query<T> in(String field, Object[] values)field IN (…).
public Query<T> orderBy(String field, boolean ascending)Orders by a field, ascending or descending.
public Query<T> limit(int count)At most this many rows.
public Query<T> offset(int count)Skips this many rows.
public List<T> list() throws IOExceptionThe matching rows, as entities.
public T first() throws IOExceptionThe first matching row, or null.
public long count() throws IOExceptionHow many rows match.
public int delete() throws IOExceptionDeletes every matching row and answers how many.
public String toString()The conditions as SQL, for a message or for a statement built around them.

Inherited methods

Method details

eq

public Query<T> eq(String field, Object value)
field = value, or field IS NULL when the value is null.

ne

public Query<T> ne(String field, Object value)
field <> value, or field IS NOT NULL when the value is null.

gt

public Query<T> gt(String field, Object value)
field > value.

gte

public Query<T> gte(String field, Object value)
field >= value.

lt

public Query<T> lt(String field, Object value)
field < value.

lte

public Query<T> lte(String field, Object value)
field <= value.

like

public Query<T> like(String field, String pattern)
field LIKE pattern, with the engine’s own wildcards: % for any run of characters and _ for one. The pattern is BOUND rather than pasted, so a value holding a quote is a value and not a statement.

isNull

public Query<T> isNull(String field)
field IS NULL.

isNotNull

public Query<T> isNotNull(String field)
field IS NOT NULL.

in

public Query<T> in(String field, Object[] values)
field IN (…). An empty or absent set matches nothing, which it says as a condition that is false rather than by dropping the clause – a filter that silently disappears returns every row in the table.

orderBy

public Query<T> orderBy(String field, boolean ascending)
Orders by a field, ascending or descending. Several calls order by each in turn.

limit

public Query<T> limit(int count)
At most this many rows.

offset

public Query<T> offset(int count)
Skips this many rows. Pair it with an order, or the rows skipped are arbitrary.

list

public List<T> list() throws IOException
The matching rows, as entities.

first

public T first() throws IOException

The first matching row, or null.

Asks the database for one row rather than reading them all and taking the first: the limit is part of the statement.

count

public long count() throws IOException

How many rows match.

The ordering and the limit are left off, because neither changes an answer that is one number – and because MySQL refuses ORDER BY in some places where a count is legal.

delete

public int delete() throws IOException

Deletes every matching row and answers how many.

ONE statement rather than a read followed by deletes, which is both faster and atomic – and which is why it is here rather than left to the caller: written by hand it is a loop that can be interrupted halfway.

A query with NO conditions deletes the whole table, exactly as the SQL it builds would. That is the reading with no surprises in it, and it is what makes this the idiomatic way to empty a table in a test.

The ordering and the limit are not part of it: MySQL alone accepts a LIMIT on a DELETE, so honouring one here would mean a query that behaves differently on the engine it was not developed against.

toString

public String toString()
The conditions as SQL, for a message or for a statement built around them.