by ampatspell
in Code
Gaeds is my tiny AppEngine for Java low-level DatastoreService wrapper. This is forth post about new features that will form 1.2 final release.
The first three are:
Both new features are related to inheritance handling so lets start with 3 models:
@Model public class Transaction { } @Model(discriminator = "handled") public class HandledTransaction extends Transaction { } @Model(discriminator = "amount") public class AmountTransaction extends HandledTransaction { }
Those three models shares single kind of "Transaction".
Now it is possible to query for keysOnly() while getting (more) correct model classes:
Iterable<HandledTransaction> iterable = getSession().query(). model(HandledTransaction.class). eq("failed", false). eq("otherTransactionKey", null). limit(limit). keysOnly(). asIterable(); for (HandledTransaction transaction : iterable) { // ... }
Prepared query is:
SELECT __key__
FROM Transaction
WHERE _discriminator = handled
AND failed = false
AND otherTransactionKey = NULL
While keysOnly() query doesn’t return actual type (In this case it can also be AmountTransaction — see next feature why) at least it is not base Transaction instance anymore.
Here is all three queries:
session.query().model(<Model>.class).keysOnly().asList();
| Model and returned instance class | DatastoreService Query |
|---|---|
Transaction.class |
SELECT __key__ FROM Transaction |
HandledTransaction.class |
SELECT __key__ FROM Transaction WHERE _discriminator = handled |
AmountTransaction.class |
SELECT __key__ FROM Transaction WHERE _discriminator = amount |
Of course this also works for SELECT * FROM queries with the difference that returned instance clases will be actual sub-classes:
session.query().model(<Model>.class).asList();
| Model and returned instance class | DatastoreService Query |
|---|---|
Transaction.class |
SELECT * FROM Transaction |
HandledTransaction.class |
SELECT * FROM Transaction WHERE _discriminator = handled |
AmountTransaction.class |
SELECT * FROM Transaction WHERE _discriminator = amount |
As we saw previously to query any HandledTransaction (this includes all HandledTransaction and also AmountTransaction entities) we need to query with two different "_discriminator" values. This is not supported in AppEngine Datastore. Instead if given model is subclass of model which is already a model what has discriminator value set, the "_discriminator" property becomes list property listing all discriminators:
| Model | Discriminators |
|---|---|
Transaction.class |
— |
HandledTransaction.class |
“handled” — String |
AmountTransaction.class |
[“amount”, “handled”] — List<String> |
This allows to query any entity that is HandledTransaction or AmountTransaction.
To take advantage of those new features, enties what has parent entity with discriminator set (in this example only AmountTransaction), needs to be migrated.
To migrate just get or query them followed by put afterwards:
Session session = getSession(); // Query will work because this was the _discriminator value that was saved before // SELECT * FROM Transaction WHERE _discriminator = amount Iterable<AmountTransaction> list = session.query(). model(AmountTransaction.class). limit(500). asIterable(); // gaeds will re-populate _discriminator value session.put(list);