Class Dao<T>
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 TypeMethodDescriptionlongcount()How many rows the table holds.voidCREATE TABLE IF NOT EXISTS, in this engine's spelling.booleanDeletes the row whose keyentitycarries.booleandeleteById(Object id) Deletes the row with this key.voidDROP TABLE IF EXISTS.Rows matching a WHERE clause written by hand, for the query the builder cannot express.findAll()Every row.The row with this key, or null.The first row matching a hand-written WHERE clause, or null.voidInsertsentity.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.voidPuts 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.type()The entity class.booleanUpdates every non-key column of the row whose keyentitycarries.
-
Method Details
-
type
The entity class. -
tableName
The table name, from @Entity(table) or the class's simple name. -
createTable
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
-
insert
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
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
Updates every non-key column of the row whose keyentitycarries.- 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
Deletes the row whose keyentitycarries.- Throws:
IOException
-
deleteById
Deletes the row with this key.- Throws:
IOException
-
findById
-
findAll
-
count
-
query
-
find
Rows matching a WHERE clause written by hand, for the query the builder cannot express.
whereis appended after WHERE and its ? are bound fromparams. 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
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
-