Trouble Deleting Objects from one to many relations list Android

Hello,

I have a table called Companies and another called Categories. Now each company can have many categories so I made a one to many relation column in the Companies table to handle that. Now each company has a list of categories and I can add to this list with no problems but I’m having trouble removing from this list.

Basically I’m doing the same thing as here https://backendless.com/documentation/data/android/data_relations_delete.htm but with no luck. Here is a piece of my code:

company.getCategoriesArray().remove(j);


for(int i=0;i<company.getCategoriesArray().size();i++){
    Log.d("cateName", company.getCategoriesArray().get(i).getCategoryName());
}
Backendless.Persistence.of(Companies.class).save(company, new AsyncCallback&lt;Companies&gt;() {
    @Override
    public void handleResponse(Companies response) {
        Toast.makeText(EditProfileActivity.this, "works?", Toast.LENGTH_LONG).show();
    }

    @Override
    public void handleFault(BackendlessFault fault) {
        Toast.makeText(EditProfileActivity.this, "doesn't work :(", Toast.LENGTH_LONG).show();
    }
});

The object gets removed from the list, and the save is always successful but when I check the database there are no changes. It’s not too complicated so there must be something I am missing.

Hello!

Please show the code where you retrieve parent object with related collection from database. Or you’re using “autoload” feature for it?
Thanks!
Alex

String whereClause = "professional.objectId = '" + String.valueOf(Backendless.UserService.CurrentUser().getObjectId()) + "'";

BackendlessDataQuery dataQuery = new BackendlessDataQuery();
dataQuery.setWhereClause(whereClause);
QueryOptions queryOptions = new QueryOptions();
queryOptions.addRelated("categoriesArray");
queryOptions.addRelated("townArray");
queryOptions.setRelationsDepth(1);
dataQuery.setQueryOptions(queryOptions);

Backendless.Persistence.of(Companies.class).find(dataQuery, new AsyncCallback&lt;BackendlessCollection&lt;Companies&gt;>() {
    @Override
    public void handleResponse(BackendlessCollection&lt;Companies&gt; response) {
        Log.d("testCompany", response.getData().get(0).getName());
        company = response.getData().get(0);
    }

    @Override
    public void handleFault(BackendlessFault fault) {
        Log.d("FAULT", String.valueOf(fault));
    }
});

Unfortunately, I cannot reproduce your issue.

Please check your “Companies” and “Categories” classes. They should have:

  1. Getters and setters for all properties
  2. Public no-argument constructor
    Also try adding the following lines before making any calls to Backendless:
Backendless.Data.mapTableToClass( "Companies", Companies.class );
Backendless.Data.mapTableToClass( "Categories", Categories.class );

Notify us about results please.
Alex

These are my classes:

public class Categories implements Serializable {

    String CategoryName;
    String objectId;
    boolean proAvailable;
    Date updated;

    public Categories(){
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    public boolean isProAvailable() {
        return proAvailable;
    }

    public void setProAvailable(boolean proAvailable) {
        this.proAvailable = proAvailable;
    }

    public String getCategoryName() {
        return CategoryName;
    }

    public void setCategoryName(String categoryName) {
        CategoryName = categoryName;
    }

    public String getObjectId() {
        return objectId;
    }

    public void setObjectId(String objectId) {
        this.objectId = objectId;
    }
}
public class Companies implements Serializable {

    String name;
    String address;
    String telefono;
    String facebook;
    String google;
    String twitter;
    String imageUrl;
    String status;
    String objectId;
    List&lt;Categories&gt; categoriesArray;
    List&lt;Cities&gt; townArray;
    List&lt;Categories&gt; pendingCategories;
    BackendlessUser professional;
    Date FechaInicio;
    Date FechaExpiracion;

    public Companies(){
    }
    public Date getFechaInicio() {
        return FechaInicio;
    }

    public void setFechaInicio(Date fechaInicio) {
        FechaInicio = fechaInicio;
    }

    public Date getFechaExpiracion() {
        return FechaExpiracion;
    }

    public void setFechaExpiracion(Date fechaExpiracion) {
        FechaExpiracion = fechaExpiracion;
    }

    public List&lt;Categories&gt; getPendingCategories() {
        return pendingCategories;
    }

    public void setPendingCategories(List&lt;Categories&gt; pendingCategories) {
        this.pendingCategories = pendingCategories;
    }

    public String getObjectId() {
        return objectId;
    }

    public void setObjectId(String objectId) {
        this.objectId = objectId;
    }

    public List&lt;Cities&gt; getTownArray() {
        return townArray;
    }

    public void setTownArray(List&lt;Cities&gt; townArray) {
        this.townArray = townArray;
    }

    public List&lt;Categories&gt; getCategoriesArray() {
        return categoriesArray;
    }

    public void setCategoriesArray(List&lt;Categories&gt; categoriesArray) {
        this.categoriesArray = categoriesArray;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public BackendlessUser getProfessional() {
        return professional;
    }

    public void setProfessional(BackendlessUser professional) {
        this.professional = professional;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTelefono() {
        return telefono;
    }

    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }

    public String getFacebook() {
        return facebook;
    }

    public void setFacebook(String facebook) {
        this.facebook = facebook;
    }

    public String getGoogle() {
        return google;
    }

    public void setGoogle(String google) {
        this.google = google;
    }

    public String getTwitter() {
        return twitter;
    }

    public void setTwitter(String twitter) {
        this.twitter = twitter;
    }

}

I added these lines before I made the call to save the Company object with the updated categories list but it didn’t work. Do I have to add them at the beginning of every activity I’m going to use backendlesss in, or by just adding it to one activity should work?

Backendless.Data.mapTableToClass( "Companies", Companies.class );
Backendless.Data.mapTableToClass( "Categories", Categories.class );

Classes look well. Provide your application id please.

Answering your question: the best way is to add these lines somewhere near Backendless.initApp() call.

Application ID: 81E8DB2E-438E-FE74-FFD2-8CF6DA3E8F00

Ok, lets try the following.

  1. Create a test “Companies” object and a few test “Categories” objects
  2. Chain them with relation
  3. Try to execute the following code (put created “Companies” objectId):
    final String parentObjectId = “companies_object_id”;
    String whereClause = “objectId=’” + parentObjectId + “’”;

BackendlessDataQuery query = new BackendlessDataQuery( whereClause );

QueryOptions options = new QueryOptions();
options.addRelated( “categoriesArray” );
options.setRelationsDepth( 1 );

query.setQueryOptions( options );

Backendless.Persistence.of( Companies.class ).find( query, new AsyncCallback<BackendlessCollection<Companies>>()
{
@Override
public void handleResponse( BackendlessCollection<Companies> complaniesBackendlessCollection )
{
Companies foundParent = companiesBackendlessCollection.getData().get( 0 );

System.out.println( foundParent.getCompaniesArray().size() );
foundParent.getCompaniesArray().remove( 0 );

Backendless.Data.of( Companies.class ).save( foundParent, new AsyncCallback<Companies>()
{
@Override
public void handleResponse( Companies parent )
{
System.out.println( parent.getCompaniesArray().size() );
}

@Override
public void handleFault( BackendlessFault backendlessFault )
{
System.out.println( "Cannot update parent: " + backendlessFault.getMessage() );
}
} );
}

@Override
public void handleFault( BackendlessFault backendlessFault )
{
System.out.println( "Cannot retrieve parent: " + backendlessFault.getMessage() );
}
} );
You should be able to see related collection size before and after updatement. Second value should be firstValue - 1. Notify me about result please.

Yup it gave me the correct result, I’ll check my code against this one to see if there are any differences. This is the result:

I/System.out: 2
I/System.out: 1

Could the problem be that I’m passing the Company object to the other activity instead of doing a search for it?

The workflow goes like this. The company can see its profile which is one activity and when they press edit profile it goes to EditProfile Activity. I pass the object from view profile to edit profile through a bundle and if there were any changes I then save the object. Should I instead search for the company again in the Edit Profile activity?

Finally got it working, for some reason when I passed the object between activities the delete was not working but I could add to the relation no problem. Instead of passing the object between activities I just passed the objectId and made a query for the object in the EditProfile Activity and now I can remove from the list.

Yes, it was the reason.

The thing is that for this kind of operations it’s important to work with retrieved object itself, but after passing it through bundle to other activity you’ll be working with its clone.
We shall discuss this case and maybe fix it in the future releases.
Thank you for being with us!