Class Dao<T>

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

public final class Dao<T> extends Object

Typed access to one entity's table.

Reached through EntityManager.dao(Class), never constructed: the statements it issues were generated from the entity at build time, and the instance is bound to the entity manager that supplies its connections.

Dao<Note> notes = em.dao(Note.class);
Note note = new Note();
note.title = "first";
notes.insert(note);              // note.id is now the generated key
List<Note> recent = notes.query()
        .eq("author", author)
        .orderBy("created", false)
        .limit(20)
        .list();

Each method takes a connection from the pool for exactly its own statement and gives it straight back, so a dao is safe to share between handlers and holds nothing between calls. Several statements that have to be one go through EntityManager.transaction(EntityManager.Work), which pins one connection for the body.

  • Method Summary

    Modifier and Type
    Method
    Description
    long
    How many rows the table holds.
    void
    CREATE TABLE IF NOT EXISTS, in this engine's spelling.
    boolean
    delete(T entity)
    Deletes the row whose key entity carries.
    boolean
    Deletes the row with this key.
    void
    DROP TABLE IF EXISTS.
    find(String where, Object[] params)
    Rows matching a WHERE clause written by hand, for the query the builder cannot express.
    Every row.
    The row with this key, or null.
    findOne(String where, Object[] params)
    The first row matching a hand-written WHERE clause, or null.
    void
    insert(T entity)
    Inserts entity.
    A query built from field names, which is the portable way to ask: the names are the entity's Java fields and the builder quotes the columns they map to, so the same query runs on all three engines.
    void
    Puts the generated key back in step after rows were inserted with keys of their own.
    The table name, from @Entity(table) or the class's simple name.
    The entity class.
    boolean
    update(T entity)
    Updates every non-key column of the row whose key entity carries.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • type

      public Class type()
      The entity class.
    • tableName

      public String tableName()
      The table name, from @Entity(table) or the class's simple name.
    • createTable

      public void createTable() throws IOException

      CREATE TABLE IF NOT EXISTS, in this engine's spelling.

      This is a convenience for development and for tests, not a migration tool: it creates a table that is not there and does nothing at all to one that is, so a column added to the entity later does not appear. A schema that changes over time wants whatever the team runs migrations with.

      Throws:
      IOException
    • dropTable

      public void dropTable() throws IOException
      DROP TABLE IF EXISTS.
      Throws:
      IOException
    • insert

      public void insert(T entity) throws IOException

      Inserts entity.

      When the key is the database's to assign -- @Id(autoIncrement = true), which is the default -- the generated key is read back into the entity before this returns, on every engine. That is the operation the three disagree about most: PostgreSQL has no last-insert-id and answers through INSERT ... RETURNING instead. See Database.insert(String, Object[], String).

      Throws:
      IOException
    • resyncGeneratedKey

      public void resyncGeneratedKey() throws IOException

      Puts the generated key back in step after rows were inserted with keys of their own.

      Supplying your own key is a supported thing -- a data import, a test fixture, a restore -- and on SQLite and MySQL doing it also moves the counter, so the next generated insert carries on above what is there. On PostgreSQL it does not: an explicit value leaves the identity's sequence where it was, and the next generated insert reuses a key that already exists. MEASURED on a fresh table, explicit id 1 followed by a generated insert: SQLite and MySQL answer 2, PostgreSQL fails with "duplicate key value violates unique constraint".

      Call this once after an import. It is a no-op on the engines that need none, so the caller writes the same line whatever it is deployed against -- which is the whole reason it is here rather than in every importer.

      Nothing calls it for you: the ORM's own insert never supplies a key for a generated column, so it cannot tell that an import happened.

      Throws:
      IOException
    • update

      public boolean update(T entity) throws IOException
      Updates every non-key column of the row whose key entity carries.
      Returns:
      whether a row matched. False is the answer a handler turns into a 404, and it is why this returns something where the client's dao returns void: on a server the row that was not there is a case, not an impossibility.
      Throws:
      IOException
    • delete

      public boolean delete(T entity) throws IOException
      Deletes the row whose key entity carries.
      Throws:
      IOException
    • deleteById

      public boolean deleteById(Object id) throws IOException
      Deletes the row with this key.
      Throws:
      IOException
    • findById

      public T findById(Object id) throws IOException
      The row with this key, or null.
      Throws:
      IOException
    • findAll

      public List<T> findAll() throws IOException
      Every row.
      Throws:
      IOException
    • count

      public long count() throws IOException
      How many rows the table holds.
      Throws:
      IOException
    • query

      public Query<T> query()
      A query built from field names, which is the portable way to ask: the names are the entity's Java fields and the builder quotes the columns they map to, so the same query runs on all three engines.
    • find

      public List<T> find(String where, Object[] params) throws IOException

      Rows matching a WHERE clause written by hand, for the query the builder cannot express.

      where is appended after WHERE and its ? are bound from params. It is SQL, so what it names is COLUMNS rather than fields, and an unquoted name in it folds to lower case on PostgreSQL the way any unquoted name does -- which is the portability the builder keeps and this gives up. Never build it by concatenating a value: that is the injection this whole surface exists to make unnecessary.

      Throws:
      IOException
    • findOne

      public T findOne(String where, Object[] params) throws IOException

      The first row matching a hand-written WHERE clause, or null.

      Asks the database for ONE row. Reading them all and keeping the first is the same answer and an unbounded amount of work to get it: a predicate that matches a large table materialised the whole of it, mapped every row into an entity, and then dropped all but one. Query.first() has always done this; this is the hand-written half catching up.

      Throws:
      IOException