Class Query<T>

java.lang.Object
com.codename1.backend.orm.Query<T>

public final class Query<T> extends Object

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(String, Object[]) takes the SQL that says it.

  • 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.
      Throws:
      IOException
    • 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.

      Throws:
      IOException
    • 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.

      Throws:
      IOException
    • 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.

      Throws:
      IOException
    • toString

      public String toString()
      The conditions as SQL, for a message or for a statement built around them.
      Overrides:
      toString in class Object