-
Notifications
You must be signed in to change notification settings - Fork 6
Second Tutorial Part 5: Basic APIs
Previous | Main | Next |
---|---|---|
<-- Part 4 | Main | Part 6 --> |
At the most basic level, you want to be able to do a simple CRUD cycle, i.e., Create/Read/Update/Delete. In a Factory/Data architecture, you can expect to use the Factory to:
- Create a new object instance
- Lookup one or more object instances
- Allow object instances (i.e., records) to be updated.
The way Tilda generates its APIs is completely defined by the Tilda JSON definition:
- In order to create a new objects, you ave to make sure that at least ALL not-null fields are set.
- In order to lookup an object, you generally have to have a primary key, or any other natural identity (i.e., a unique index).
- In order to lookup a list of objects, you generally have to have one or more fields, generally mapping to a non-unique index.
If we take the User entity defined in this tutorial, it's defined as follows:
{ "name":"User"
,"description":"Users"
,"columns":[
{ "name":"id" , "type":"STRING", "size": 40, "nullable":false, "description":"The user's id" }
,{ "name":"email", "type":"STRING", "size":255, "nullable":false, "description":"The user's email" }
,{ "name":"name" , "type":"STRING", "size":255, "nullable":true , "description":"The user's full name" }
]
,"primary": { "autogen": true, "keyBatch": 500 }
,"indices": [
{ "name":"Id" , "columns": ["id" ] }
,{ "name":"Email", "columns": ["email"] }
,{ "name":"All" , "orderBy": ["lastUpdated desc"]}
]
}
We have defined all those things:
- A set of not-null fields (
id
andemail
) - A primary Key (auto-generated, and thus,
refnum
) - Two natural identities (unique indices, i.e., indices without an orderBy definition)
- The unique Index
Id
covering the fieldid
- The unique Index
Email
covering the fieldemail
- The unique Index
- A non-unique index
- The index
All
with only an orderBy overlastUpdated
- The index
Every one of those definitions in effect will generate APIs in the factory class, respectively:
static public User_Data create(String id, String email) throws Exception;
static public User_Data lookupByPrimaryKey(long refnum) throws Exception;
static public User_Data lookupById(String id) throws Exception;
static public User_Data lookupByEmail(String email) throws Exception;
static public ListResults<User_Data> lookupWhereAll(Connection C, int Start, int Size) throws Exception;
At the core of Tilda in Java, we establish compile-time artifacts that capture the semantics of the entity at many levels. This helps a lot when doing rapid iterative development (the 'I' in Tilda) where the semantics of entities will invariably change. With compile-time artifacts, a change in not-null fields will change the create() API and as such, it will be flagged anywhere it's used throughout your code. Other frameworks using run-time code generation are unable to do this typically. Similarly, removing or changing a natural identity (a unique index constraint), or changing privileged access methods (backed by indices in the database) will change Factory-level APIs and will immediately be flagged by the compiler across a project.
🎈 NOTE: In our experience, this is fairly radical as it encourages "breaking the schema" without fear of actually breaking the application at runtime accidentally. Complex migrations already handled automatically by the Migrate utility are also supported natively of sorts through the Java compiler.
🎈 NOTE: If you look closely, there is a material difference between the lookupByXxx
methods that return a single Object, and the lookupWhereXxx
methods that return a list: The lookupWhereXxx
methods take in a Connection object. This is a pattern throughout the Tilda API: passing a Connection object to an API implies that API will access the database. We'll see below how this manifests itself in practice, but:
- The
lookupWhereXxx
methods access the data store by executing a select query and returning 0 or more records that have been fully read from the data store. - The
create
andlookupByXxx
methods initialize an in-memory object that can then be further manipulated or modified until it is actually written to or read from the data store (using theread(Connection C)
andwrite(Connection C)
APIs in the Data object.
As for the Data class, you will find all the getters and setters you might expect, as well as the read(Connection C)
and write(Connection C)
methods to read/write the record from/to the data store. The read
method will typically called after a lookupBy
whereas the write
method will be called after a create
or after an object's state has been modified via setters.
🎈 NOTE: There are settings when defining an entity in the Tilda JSON definition file that will affect how those methods are generated. For example:
-
invariant
fields will have a setter that will fail if it's used at any time after an object has been written to the database. - A nullable field will have an
isXxxNull()
method whereas a not-null field won't. - If the entity's
lc
(life-cycle) is defined as READ_ONLY, then the Write method and setters won't be generated. - If the entity's
lc
is WORM (Write Once Read Many), setters and write will fail after the first time an object was initially created (i.e., inserts and selects only, but no update).
Previous | Main | Next |
---|---|---|
<-- Part 4 | Main | Part 6 --> |