Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.
public final class EntityManager
- Object
- EntityManager
The entry point to the build-time ORM: entities in, daos out.
EntityManager em = EntityManager.open(dataSource);
Dao<Note> notes = em.dao(Note.class);
The conventions are the client’s, deliberately. An entity is a class with
@Entity, @Id, @Column and @DbTransient on it;
the build reads those out of the compiled class and writes the dao; the dao
issues prepared statements and never reflects. What differs on this side is
what it issues them THROUGH: Database, so the
same entity class is stored in the app’s SQLite file and in the server’s
PostgreSQL, and only the connection knows which.
How a dao gets here
Nothing looks a class up by name. The build writes one
<Entity>Cn1BackendDao per entity and a
cn1app.BackendDaoBootstrap whose constructor registers every one of
them, and the generated server entry point runs that before it starts
listening.
That entry point is the ONLY thing that can run it. The bootstrap is
generated during process-classes, after javac has compiled the module’s own
sources, so a main written by hand cannot name it – a module that
sets its own mainClass reaches the database through DataSource and not
through this.
The names are not the client’s – there the dao is <Entity>Cn1Dao
and the bootstrap is cn1app.DaoBootstrap – because an entity shared
between an application and its server has BOTH generated for it, and the two
have to be able to sit on one classpath.
That indirection is not ceremony. The translator drops a class nothing
references, and obfuscation renames the ones that survive, so a registry
populated by scanning or by Class.forName would be empty in exactly the
builds that ship. A generated class holding a direct reference to each dao is
what keeps them alive, and the registry is keyed on Class.getName(),
which registration and lookup agree about within one execution however the
names were rewritten.
An entity manager takes its snapshot of the registry when it is opened, so everything is resolved once at start-up and a request never contends on a map.
Nested types
interface EntityManager.Work | A unit of work run inside transaction. |
Methods
Inherited methods
Method details
register
public static void register(EntityDefinition definition)registered
public static EntityDefinition[] registered()open
public static EntityManager open(DataSource pool)
throws IOExceptionThrows
open
public static EntityManager open(Database db)
throws IOExceptionThrows
dao
public <T> Dao<T> dao(Class<T> entity)The dao for an entity class.
Resolved from the snapshot taken when this manager was opened, so it allocates nothing and cannot fail for a class that was registered before then. A class that was not registered says so, because the cause is nearly always one of two things: the annotation is missing, or the generated bootstrap was never run.
openSession
public Session openSession()Returns
Throws
IllegalStateException- if called on a transaction-scoped manager
createTables
public void createTables()
throws IOExceptionCreates the table of every registered entity that has none.
For development and for tests. Production schemas are migrations, and this creates a table without ever altering one, so it cannot be that.
Throws
transaction
public Object transaction(EntityManager.Work body)
throws ExceptionRuns body inside one transaction on one connection.
The entity manager the body is handed is pinned to that connection, so every dao reached through it is inside the transaction. A dao taken from the OUTER manager is not – that borrows a second connection, which the database sees as another session.
An entity manager that is already pinned joins the transaction it is in rather than opening another: all three engines refuse a nested BEGIN, and a service method that works alone should not break when another one calls it.
Throws
dataSource
public DataSource dataSource()database
public Database database()dialect
public Dialect dialect()Dialect.close
public void close()Closes the pool, or the connection, this manager was opened over.
The manager handed to a transaction body owns nothing and closes
nothing: the connection under it belongs to the transaction, which is not
over. One opened over a caller’s Database does close it, which is
what the sentence above promises and what the client-side entity manager
does – leaving it open made repeated open/use/close cycles leak a SQLite
handle or a network session each time.