Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.
public final class DataSource
- Object
- DataSource
A pool of connections to ONE database, whichever engine that database is.
DbPool pools SQLite and only SQLite – it opens connections from a
file path, so there is nowhere to put a host, a user or a password. That left
the server engines with the advice to share a single Database and
accept that every handler queues behind whichever exchange is on the socket,
because a Database over PostgreSQL or MySQL owns one wire connection and
synchronizes every operation on it.
Queueing is the right default for a server whose database is a local file. It is the wrong one for a server whose database is a machine across a network that is perfectly happy to run eight statements at once: there the single connection is not a safety property, it is the bottleneck. This is the same pool for all three, so which engine is behind it stops being a question the application’s structure has to answer.
DataSource db = DataSource.open("postgres://user:pw@db.internal/app");
List rows = db.query("SELECT id, title FROM notes WHERE author = ?",
new Object[] {author});
The convenience methods above borrow a connection, run one statement and
release it, which is what a handler wants: it is the borrow held ACROSS
unrelated work that empties a pool. inTransaction is the form for
several statements that have to be one, and it holds exactly one connection
for exactly the body.
Connections are opened lazily except the first, which is opened by
open so that a wrong URL, an unreachable host or a refused password
fails at start-up rather than on the first request that needed the database.
An in-memory SQLite database is pooled at size one, and a configuration asking for more is REFUSED rather than quietly reduced. Each connection to “:memory:” gets its OWN private database, so a pool of them hands successive requests different empty databases – the one case where a bigger pool is not slower but wrong, and a setting worth reporting rather than ignoring.
Nested types
interface DataSource.Work | A unit of work run against one borrowed connection. |
Methods
Inherited methods
Method details
open
public static DataSource open(String url)
throws IOExceptionurl names.Throws
open
public static DataSource open(String url, int size)
throws IOExceptionsize connections; 0 takes the default for the engine.Throws
open
public static DataSource open(String url, int size, int busyTimeoutMillis, long borrowTimeoutMillis)
throws IOExceptionParameters
urlString- Not documented.
sizeint- how many connections at most; 0 for the engine’s default
busyTimeoutMillisint- how long SQLite waits on a locked database; ignored by the server engines, which have no such setting
borrowTimeoutMillislong- how long a borrow waits for a free connection before failing; 0 waits forever
Throws
fromConfig
public static DataSource fromConfig(Config config)
throws IOExceptionThe pool a Config describes, which is the one a server normally
wants: the URL comes from the deployment rather than from the source.
With no URL configured at all this answers an in-memory SQLite database on a development profile, and refuses on any other. Defaulting silently in production is how a service comes up healthy, serves requests, writes everything into a database inside its own process and loses all of it at the next deploy.
Throws
of
public static DataSource of(Database db)
throws IOExceptionA pool of one around a connection somebody else opened, for code that has a
Database already and wants the pooled API around it.
The connection is NOT closed by close: it belongs to whoever
opened it.
Throws
borrow
public synchronized Database borrow()
throws IOExceptionThrows
release
public synchronized void release(Database db)withConnection
public Object withConnection(DataSource.Work body)
throws ExceptionThrows
inTransaction
public Object inTransaction(DataSource.Work body)
throws ExceptionOne transaction on one borrowed connection.
Everything the body does through the Database it is handed is inside that transaction. Anything it does through THIS pool is not: that borrows a second connection, which the database sees as another session entirely, and on SQLite it will simply block against the write lock the first one holds.
Throws
execute
public int execute(String sql, Object[] params)
throws IOExceptionThrows
query
public List query(String sql, Object[] params)
throws IOExceptionThrows
queryOne
public Map queryOne(String sql, Object[] params)
throws IOExceptionThrows
insert
public long insert(String sql, Object[] params, String idColumn)
throws IOExceptionOne INSERT on a borrowed connection, answering the key the database generated.
The connection is held across the insert AND the question that reads the key back, which is what makes the answer this insert’s on the engines where the key is a property of the session – SQLite’s last_insert_rowid and MySQL’s LAST_INSERT_ID both answer for the connection they are asked on. A pooled insert that released between the two would read whatever the next borrower had done.
Throws
dialect
public Dialect dialect()Dialect.getMaxSize
public int getMaxSize()getOpenCount
public synchronized int getOpenCount()getIdleCount
public synchronized int getIdleCount()close
public synchronized void close()toString
public String toString()