3

I am having problems with ObjectBox in my Android app. Everything works, except for this issue, so I know my entity classes are OK.

It's an inventory that makes it possible to do inventories of multiple shops (stores). Each InventoryItem is a product that was scanned when doing the inventory. When the inventory is concluded, one or more text files are generated from the data in the box.

One file is generated for each shop, so I have this code to find which distinct shops were inventoried:

Box<InventoryItem> box = app.getBoxStore().boxFor(InventoryItem.class);
long[] shopIds = box.query()
                    .build()
                    .property(InventoryItem_.shopId)
                    .distinct()
                    .findLongs();

I get the following when this code runs (only relevant part of the stacktrace):

Caused by: java.lang.IllegalArgumentException: Property "shopId" is of type Relation, but we expected a property of type Long in this context
    at io.objectbox.query.PropertyQuery.nativeFindLongs(Native Method)
    at io.objectbox.query.PropertyQuery$2.call(PropertyQuery.java:213)
    at io.objectbox.query.PropertyQuery$2.call(PropertyQuery.java:210)
    at io.objectbox.BoxStore.callInReadTx(BoxStore.java:709)
    at io.objectbox.BoxStore.callInReadTxWithRetry(BoxStore.java:654)
    at io.objectbox.query.Query.callInReadTx(Query.java:273)
    at io.objectbox.query.PropertyQuery.findLongs(PropertyQuery.java:210)
    at br.com.donadio.inventario.view.ExportDialog$GenerateFilesAsync.doInBackground(ExportDialog.java:132)
    at br.com.donadio.inventario.view.ExportDialog$GenerateFilesAsync.doInBackground(ExportDialog.java:104)
    at android.os.AsyncTask$2.call(AsyncTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
    at java.lang.Thread.run(Thread.java:761) 

I also tried using .property(InventoryItem_.shop.targetIdProperty) in the query, but it gives the exact same error. I can't find another way to do this, nor a way to fix my code.

I'm using AndroidX (not that it should matter) and my project is correctly setup for it. MinSdk is 19, MaxSdk is 28, targetSdk is 28. ObjectBox version is 2.2.0. Debugging on a device running Android 7.1.1.

These are the relevant entities:

@Entity
public class InventoryItem
{
    @Id
    public long id;

    public String operator;

    public ToOne<Area> area;
    public long areaId; // expose relationship target ID

    public ToOne<Product> product;
    public long productId; // expose relationship target ID

    public ToOne<Shop> shop;
    public long shopId; // expose relationship target ID

    public Date timestamp;

    // ...
}

@Entity
public class Shop
{
    @Id(assignable=true)
    public long id;

    @Index @Unique
    public String name;

    @Backlink
    public ToMany<InventoryItem> inventoryItems;

    // ...
}

2 Answers 2

1

After looking a lot for an answer in ObjectBox's GitHub and here, I came up with a solution, based on this answer on the project's GitHub:

List<InventoryItem> items = box.getAll();
ArrayList<Shop> shops = new ArrayList<>();
for (InventoryItem item : items)
{
    Shop shop = item.shop.getTarget();
    if (!shops.contains(shop))
        shops.add(shop);
}

So, we just find everything and then iterate through the list, getting distinct objects in an ArrayList (or I could just get the Id's into a long[]) . Just a handful more lines of code...

Still, I consider that a bug in ObjectBox's implementation, as it's returning a relationship instead of a property on a long attribute. I'm opening an issue.

Sign up to request clarification or add additional context in comments.

Comments

0

Workaround I found is to write your query using the object you want the ID from as the starting class.

In your case, that would be :

QueryBuilder<Shop> qb = app.getBoxStore().boxFor(Shop.class).query(); // Start with Shop if what you need are Shop IDs
qb.link(Shop_.inventoryItems); // Filter on working inventoryItems links
long[] shopIds = qb.build()
                    .property(Shop_.id)
                    .distinct()
                    .findLongs(); // Get your IDs

instead of

Box<InventoryItem> box = app.getBoxStore().boxFor(InventoryItem.class);
long[] shopIds = box.query()
                    .build()
                    .property(InventoryItem_.shopId)
                    .distinct()
                    .findLongs();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.