New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getId() returns NULL, resulting in not being able to delete objects? #78

Closed
olavbg opened this Issue Oct 6, 2015 · 10 comments

Comments

Projects
None yet
4 participants
@olavbg

olavbg commented Oct 6, 2015

I have a java class Movie:

public class Movie extends RushObject {

private String tittel = "";
private String format = "";

public Movie() {
}

public Movie(String tittel, String format){
    this.tittel = tittel;
    this.format = format;
}
//...
//getters, setters, equal & hashcode
//...

}

I create a new Movie:

Movie movie = new Movie("Thor","Blu-Ray");

And saves it:

movie.save(new RushCallback() {
   @Override
    public void complete() {
        Log.d("movie.save()",""+movie.getId());
        Snackbar.make(v, movie.getTittel() + " added.", Snackbar.LENGTH_LONG).show();
    }
});

Here movie.getId() returns a valid id.

But.. When I at startup of application runs this:

for (Movie movie : new RushSearch().orderAsc("tittel").find(Movie.class)) {
     Log.d("Found movie in DB", movie.getTittel());
     Log.d("Found movie in DB", "" + movie.getId());
}

movie.getId() is NULL:

10-06 19:16:42.815 25729-25729/com.olavbg.android.filmbase D/Found movie in DB: Thor
10-06 19:16:42.815 25729-25729/com.olavbg.android.filmbase D/Found movie in DB: null

When trying to delete this movie the callback gets called, but I see no log entry from RushOrm. Also, on the next startup the movie is still there. RushCore.deleteAll(Movie.class) and RushCore.clearDatabase() works as expected.

I searched and found this issue: #14
So I tried overriding getId() in Movie.java:

@Override
public String getId() { return RushCore.getInstance().getId(this); }

I have also tried this:

movie.save(new RushCallback() {
   @Override
    public void complete() {
        Log.d("movie.save()",""+movie.getId());
        movie.setTempId(movie.getId());
        Snackbar.make(v, movie.getTittel() + " added.", Snackbar.LENGTH_LONG).show();
    }
});

And then when deleting:

RushCore.getInstance().registerObjectWithId(movie, movie.getTempId());
movie.delete();

But still no luck.
Am I doing something wrong?

@pengrad

This comment has been minimized.

Show comment
Hide comment
@pengrad

pengrad Oct 12, 2015

I have the same issue.
Problem in hashCode(). If override it we have null getId() and empty Rush-children.

pengrad commented Oct 12, 2015

I have the same issue.
Problem in hashCode(). If override it we have null getId() and empty Rush-children.

@Stuart-campbell

This comment has been minimized.

Show comment
Hide comment
@Stuart-campbell

Stuart-campbell Oct 13, 2015

Owner

Hi,

Just had a quick look.

I think the issue is at this line https://github.com/Stuart-campbell/RushCore/blob/master/src/main/java/co/uk/rushorm/core/RushCore.java#L158

All the ids are stored in a WeakHashMap this is so a base object is not required and you can use an interface instead.

Do you use properties of the object in your hashCode override method? Also does your pull request fix the issue?

Thanks

Owner

Stuart-campbell commented Oct 13, 2015

Hi,

Just had a quick look.

I think the issue is at this line https://github.com/Stuart-campbell/RushCore/blob/master/src/main/java/co/uk/rushorm/core/RushCore.java#L158

All the ids are stored in a WeakHashMap this is so a base object is not required and you can use an interface instead.

Do you use properties of the object in your hashCode override method? Also does your pull request fix the issue?

Thanks

@olavbg

This comment has been minimized.

Show comment
Hide comment
@olavbg

olavbg Oct 13, 2015

This is my hashcode (only strings and integers, no children):

 @Override
    public int hashCode() {
        int result = filmID.hashCode();
        result = 31 * result + tittel.hashCode();
        result = 31 * result + format.hashCode();
        result = 31 * result + lagtTil.hashCode();
        result = 31 * result + brukerID;
        result = 31 * result + type.hashCode();
        result = 31 * result + year.hashCode();
        result = 31 * result + rated.hashCode();
        result = 31 * result + released.hashCode();
        result = 31 * result + runtime.hashCode();
        result = 31 * result + genre.hashCode();
        result = 31 * result + director.hashCode();
        result = 31 * result + writer.hashCode();
        result = 31 * result + actor.hashCode();
        result = 31 * result + tagline.hashCode();
        result = 31 * result + plot.hashCode();
        result = 31 * result + trailer.hashCode();
        result = 31 * result + imdb_id.hashCode();
        result = 31 * result + trakt_id.hashCode();
        result = 31 * result + poster.hashCode();
        result = 31 * result + ut.hashCode();
        result = 31 * result + dato.hashCode();
        result = 31 * result + utlanID.hashCode();
        result = 31 * result + navn.hashCode();
        result = 31 * result + (err_msg != null ? err_msg.hashCode() : 0);
        return result;
    }

olavbg commented Oct 13, 2015

This is my hashcode (only strings and integers, no children):

 @Override
    public int hashCode() {
        int result = filmID.hashCode();
        result = 31 * result + tittel.hashCode();
        result = 31 * result + format.hashCode();
        result = 31 * result + lagtTil.hashCode();
        result = 31 * result + brukerID;
        result = 31 * result + type.hashCode();
        result = 31 * result + year.hashCode();
        result = 31 * result + rated.hashCode();
        result = 31 * result + released.hashCode();
        result = 31 * result + runtime.hashCode();
        result = 31 * result + genre.hashCode();
        result = 31 * result + director.hashCode();
        result = 31 * result + writer.hashCode();
        result = 31 * result + actor.hashCode();
        result = 31 * result + tagline.hashCode();
        result = 31 * result + plot.hashCode();
        result = 31 * result + trailer.hashCode();
        result = 31 * result + imdb_id.hashCode();
        result = 31 * result + trakt_id.hashCode();
        result = 31 * result + poster.hashCode();
        result = 31 * result + ut.hashCode();
        result = 31 * result + dato.hashCode();
        result = 31 * result + utlanID.hashCode();
        result = 31 * result + navn.hashCode();
        result = 31 * result + (err_msg != null ? err_msg.hashCode() : 0);
        return result;
    }
@Stuart-campbell

This comment has been minimized.

Show comment
Hide comment
@Stuart-campbell

Stuart-campbell Oct 13, 2015

Owner

I think that pull request should fix this. I just need to run the unit tests then I can merge and do an updated release. I'll try get that done tonight.

Thanks

Owner

Stuart-campbell commented Oct 13, 2015

I think that pull request should fix this. I just need to run the unit tests then I can merge and do an updated release. I'll try get that done tonight.

Thanks

@pengrad

This comment has been minimized.

Show comment
Hide comment
@pengrad

pengrad Oct 13, 2015

Yes, I made build with this fix and everything is ok.

I'm agree that problem is in idTable.
When call didLoadObject() we put not initialized object in Map with hashCode() returning 0 (or something like 0) and after filling object's fields we try to get it with corrected hashCode().

So, I think it's not necessary to show object outside before init it.

pengrad commented Oct 13, 2015

Yes, I made build with this fix and everything is ok.

I'm agree that problem is in idTable.
When call didLoadObject() we put not initialized object in Map with hashCode() returning 0 (or something like 0) and after filling object's fields we try to get it with corrected hashCode().

So, I think it's not necessary to show object outside before init it.

@Stuart-campbell

This comment has been minimized.

Show comment
Hide comment
@Stuart-campbell

Stuart-campbell Oct 13, 2015

Owner

That was thought, good spot.

Owner

Stuart-campbell commented Oct 13, 2015

That was thought, good spot.

@olavbg

This comment has been minimized.

Show comment
Hide comment
@olavbg

olavbg Oct 13, 2015

I am using RushOrm as a depenency

compile 'co.uk.rushorm:rushandroid:1.1.10'

Will this fix be pushed as a new release anytime soon?

olavbg commented Oct 13, 2015

I am using RushOrm as a depenency

compile 'co.uk.rushorm:rushandroid:1.1.10'

Will this fix be pushed as a new release anytime soon?

@Stuart-campbell

This comment has been minimized.

Show comment
Hide comment
@Stuart-campbell

Stuart-campbell Oct 14, 2015

Owner

Hey thats fixed and in version 1.1.11.

Thanks

Owner

Stuart-campbell commented Oct 14, 2015

Hey thats fixed and in version 1.1.11.

Thanks

@Stuart-campbell Stuart-campbell added the bug label Oct 14, 2015

@olavbg

This comment has been minimized.

Show comment
Hide comment
@olavbg

olavbg Oct 16, 2015

Looks like that did the trick! Thanks 😃

olavbg commented Oct 16, 2015

Looks like that did the trick! Thanks 😃

@olavbg olavbg closed this Oct 16, 2015

@Cy4n1d3

This comment has been minimized.

Show comment
Hide comment
@Cy4n1d3

Cy4n1d3 Dec 12, 2015

@Stuart-campbell
As a follow up (if it's not related I may open up another issue):
I'm kinda in the same spot right now as olavbg has been when he opened up this ticket.

I am overwriting equals() and hashCode() as I need to compare Lists and use contains() while disregarding any FilterValues which may have been (user)set before.

I have the following (pseudocode) classes:

class Filter extends RushObject {
    private int filterId;
    String name;
    String type;
    List<FilterValue> filterValues;

    // a bunch of constructors, getters, setters, methods

    @Override
    public int hashCode() {
        int hash = 17;
        hash = 31 * hash + filterId;
        hash = 31 * hash + (name != null ? name.hashCode() : 0);
        hash = 31 * hash + (type != null ? type.hashCode() : 0);

        return hash;
    }
}

class FilterValue extends RushObject {
    private int filterValueId;
    private String value;

    // snipped
}

On first start of the application (fresh database) while modifying and saving a Filter in my FilterFragment this Filter is being duplicated afterwards (without child objects - List is being omitted in this case).
This only happens on first start, while staying in the first (Home)View without switching activities and while overwriting hashCode.
If I comment out my custom hashCode(), this object duplication does not occur.

Possibly clarifying output from logcat - relevant parts being the Filter-object and the Rush='xxx' property:
hashCode() commented out, expected behaviour:

12-12 13:59:01.532    9579-9579/pg.recsys.app.debug W/FilterListAdapter﹕ Saving Filter (row toggled) Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='false', val='false'}]}
12-12 13:59:01.544    9579-9579/pg.recsys.app.debug W/Filter﹕ RUSH Saving: Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='true', val='false'}]}

custom hashCode() in place, unexpected behaviour:

12-12 14:02:47.633  11233-11233/pg.recsys.app.debug W/FilterListAdapter﹕ Saving Filter (row toggled) Filter{fId=12, Rush='false', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='false', val='false'}]}
12-12 14:02:47.642  11233-11233/pg.recsys.app.debug W/Filter﹕ RUSH Saving: Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='true', val='false'}]}

Explanation of log output:

  • a textview with checkmark is toggled, the corresponding Filter is being modified and saved after
  • the first logcat snippet shows the wanted and expected behaviour: Rush='true', meaning the object has getId() != null; after saving, the List<> looks like I expected - no duplicated Filter objects, all children exist
  • the second logcat snipped shows something confusing: Rush='false' - afterwards we have duplicate entries inside our List<> without child objects

I could of course work around this problem by writing a custom contains() method which does not use equals() (meaning me not having to overwrite hashCode) but still I'd like to hear if such behaviour is to be expected? If yes, what's the reason for this?

PS: the same problem also applies to the FilterValue class which I've written a custom equals() and hashCode() for. As I don't need those right now I've commented them out for debugging purposes. If I use a custom hashCode on FilterValue as well, these objects also report Rush='false' on being modified after first start.

Kind regards,
Christian

Cy4n1d3 commented Dec 12, 2015

@Stuart-campbell
As a follow up (if it's not related I may open up another issue):
I'm kinda in the same spot right now as olavbg has been when he opened up this ticket.

I am overwriting equals() and hashCode() as I need to compare Lists and use contains() while disregarding any FilterValues which may have been (user)set before.

I have the following (pseudocode) classes:

class Filter extends RushObject {
    private int filterId;
    String name;
    String type;
    List<FilterValue> filterValues;

    // a bunch of constructors, getters, setters, methods

    @Override
    public int hashCode() {
        int hash = 17;
        hash = 31 * hash + filterId;
        hash = 31 * hash + (name != null ? name.hashCode() : 0);
        hash = 31 * hash + (type != null ? type.hashCode() : 0);

        return hash;
    }
}

class FilterValue extends RushObject {
    private int filterValueId;
    private String value;

    // snipped
}

On first start of the application (fresh database) while modifying and saving a Filter in my FilterFragment this Filter is being duplicated afterwards (without child objects - List is being omitted in this case).
This only happens on first start, while staying in the first (Home)View without switching activities and while overwriting hashCode.
If I comment out my custom hashCode(), this object duplication does not occur.

Possibly clarifying output from logcat - relevant parts being the Filter-object and the Rush='xxx' property:
hashCode() commented out, expected behaviour:

12-12 13:59:01.532    9579-9579/pg.recsys.app.debug W/FilterListAdapter﹕ Saving Filter (row toggled) Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='false', val='false'}]}
12-12 13:59:01.544    9579-9579/pg.recsys.app.debug W/Filter﹕ RUSH Saving: Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='true', val='false'}]}

custom hashCode() in place, unexpected behaviour:

12-12 14:02:47.633  11233-11233/pg.recsys.app.debug W/FilterListAdapter﹕ Saving Filter (row toggled) Filter{fId=12, Rush='false', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='false', val='false'}]}
12-12 14:02:47.642  11233-11233/pg.recsys.app.debug W/Filter﹕ RUSH Saving: Filter{fId=12, Rush='true', name='Raucherbereich', type='boolean', fVal=[FilterValue{fVId=23, Rush='true', val='true'}, FilterValue{fVId=24, Rush='true', val='false'}], uFVal=[FilterValue{fVId=23, Rush='true', val='false'}]}

Explanation of log output:

  • a textview with checkmark is toggled, the corresponding Filter is being modified and saved after
  • the first logcat snippet shows the wanted and expected behaviour: Rush='true', meaning the object has getId() != null; after saving, the List<> looks like I expected - no duplicated Filter objects, all children exist
  • the second logcat snipped shows something confusing: Rush='false' - afterwards we have duplicate entries inside our List<> without child objects

I could of course work around this problem by writing a custom contains() method which does not use equals() (meaning me not having to overwrite hashCode) but still I'd like to hear if such behaviour is to be expected? If yes, what's the reason for this?

PS: the same problem also applies to the FilterValue class which I've written a custom equals() and hashCode() for. As I don't need those right now I've commented them out for debugging purposes. If I use a custom hashCode on FilterValue as well, these objects also report Rush='false' on being modified after first start.

Kind regards,
Christian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment