Skip to content
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

New method `getOrCreate(RealmObject.class, primaryKey) #2166

Open
beeender opened this issue Jan 27, 2016 · 7 comments
Open

New method `getOrCreate(RealmObject.class, primaryKey) #2166

beeender opened this issue Jan 27, 2016 · 7 comments

Comments

@beeender
Copy link
Contributor

beeender commented Jan 27, 2016

Suggestion from SO
http://stackoverflow.com/questions/35017640/realmobject-with-primarykey-only

Here I figured out that there is method realm.objectForPrimaryKey(User.self, key: "key") for swift but I did not fund analog in java version.
It would be nice to have in this situation something like realm.getOrCreate(Cat.class, c.id) method. Is there any

@cmelchior
Copy link
Contributor

We actually already have something almost like it createObject(Class clazz, Object primaryKeyValue). It is used internally by the copyOrUpdate methods. It is not public right now because I was a bit concerned how well it would work with composite primary keys + It isn't very type safe. If you put in the wrong value it will crash.

That said, I seen this feature being request a couple of times as well, so maybe it is worth looking into how we can add it to the public API.

@beeender
Copy link
Contributor Author

What about

<E extends RealmObject> E getOrCreateObject(Class<E> clazz, String primaryKeyValue) { }
<E extends RealmObject> E getOrCreateObject(Class<E> clazz, byte primaryKeyValue) { }
<E extends RealmObject> E getOrCreateObject(Class<E> clazz, short primaryKeyValue) { }
<E extends RealmObject> E getOrCreateObject(Class<E> clazz, int primaryKeyValue) { }
<E extends RealmObject> E getOrCreateObject(Class<E> clazz, long primaryKeyValue) { }

For the composite primary keys, something like, and check the input during run time

<E extends RealmObject> E getOrCreateObject(Class<E> clazz, Map<String, Object> primaryKeyValue) { }

@cmelchior
Copy link
Contributor

Better, but I would hate having to add so many overloaded methods, but yeah it is a trade-off between method count and safety.

@beeender
Copy link
Contributor Author

just realized we need boxed type as well... which means there are going to be 9 methods....
by allowing null values for primary key, we probably just want methods with boxed types and checking nullability in run time

@cmelchior
Copy link
Contributor

This might be an excellent time to start looking into implementing Lint checks? i.e. we only add:

Realm.createOrGet(Class<? extends RealmObject> clazz, Object primaryKey);

and then use a Lint check on "compiletime".

That would also mean we could get starting exploring what is possible with Lint checks since there is a bunch that would make a lot of sense (checking query parameters is a good one).

@beeender
Copy link
Contributor Author

Also, we need a method only returns without creating, (return null if it doesn't exist) like:

RealmObject realmObject = Realm.get(Class<? extends RealmObject> clazz, Object primaryKey);

+1 from http://stackoverflow.com/questions/38109905/proper-way-to-get-realm-object-by-its-primary-key-in-android-java

@loudenvier
Copy link

loudenvier commented Jul 1, 2016

I've came up with a helper class which will help get any Realm object by key (returning null if there are no primary key or the object is not found). Here is the code:

public final class Find {
    // shared cache for primary keys
    private static Hashtable<Class<? extends RealmModel>, String> primaryKeyMap = new Hashtable<>();

    private static String getPrimaryKeyName(Realm realm, Class<? extends RealmModel> clazz) {
        String primaryKey = primaryKeyMap.get(clazz);
        if (primaryKey != null)
            return primaryKey;
        RealmObjectSchema schema = realm.getSchema().get(clazz.getSimpleName());
        if (!schema.hasPrimaryKey())
            return null;
        primaryKey = schema.getPrimaryKey();
        primaryKeyMap.put(clazz, primaryKey);
        return primaryKey;
    }

    private static <E extends RealmModel, TKey> E findByKey(Realm realm, Class<E> clazz, TKey key) {
        String primaryKey = getPrimaryKeyName(realm, clazz);
        if (primaryKey == null)
            return null;
        if (key instanceof String)
            return realm.where(clazz).equalTo(primaryKey, (String)key).findFirst();
        else
            return realm.where(clazz).equalTo(primaryKey, (Long)key).findFirst();
    }

    public static <E extends RealmModel> E byKey(Realm realm, Class<E> clazz, String key) {
        return findByKey(realm, clazz, key);
    }

    public static <E extends RealmModel> E byKey(Realm realm, Class<E> clazz, Long key) {
        return findByKey(realm, clazz, key);
    }
}

I've updated the Stack Overflow question: http://stackoverflow.com/questions/38109905/proper-way-to-get-realm-object-by-its-primary-key-in-android-java/38136597#38136597

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

No branches or pull requests

5 participants