Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'User' has a primary key, use 'createObject(Class<E>, Object)' instead

Tags:

android

realm

In the following Realm example,I created two models. One is called Task and the other User. With the help of Realm I am going to use the one-to-one relationship. ie. User "Theo" has one Task.

So here are my models.

@RealmClass
public class Task implements RealmModel {

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getTitle() {
    return title;
}


public void setTitle(String title) {
    this.title = title;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

@PrimaryKey
private String id;
private String title;

public boolean isCompleted() {
    return isCompleted;
}

public void setCompleted(boolean completed) {
    isCompleted = completed;
}

private String description;
private boolean isCompleted;
 }

And

@RealmClass
public class User implements RealmModel {
@PrimaryKey
private String id;
private String firstName;
private String lastName;
private Task task;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public Task getTask() {
    return task;
}

public void setTask(Task task) {
    this.task = task;
}

}

And in my main fragment I insert dummy data.

public class MainFragment extends Fragment {
private Task task;
private Realm realm;
private TextView textContent;
public MainFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_main, container, false);


    return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Handler handler = new Handler();

    final Runnable r = new Runnable() {
        public void run() {
            realm = Realm.getDefaultInstance();

            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {

                    //Create a user if there isn't one
                    if (realm.where(User.class).count() == 0) {
                        User user = realm.createObject(User.class);
                        user.setFirstName("Theo");
                        user.setLastName("Larsen");
                        user.setId(UUID.randomUUID().toString());
                    }
                }


            });


        }
    };

    handler.postDelayed(r, 1000);

    Runnable r1 = new Runnable() {
        @Override
        public void run() {

            final User u = realm.where(User.class).findFirst();


            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {


                    //Create a task
                    Task t = realm.createObject(Task.class);
                    t.setId(UUID.randomUUID().toString());
                    t.setTitle("Take out recycling");
                    t.setDescription("Do it every morning");
                    //set this task to the user.
                    u.setTask(t);

                }


            });

            Log.d("TASK","Task title: " + u.getTask().getTitle());
        }
    };
    handler.postDelayed(r1, 1000);

}

@Override
public void onDestroy() {
    super.onDestroy();
    realm.close();
}
}

However,I get this exception.

 io.realm.exceptions.RealmException: 'User' has a primary key, use 'createObject(Class<E>, Object)' instead.
                  at io.realm.Realm.createObjectInternal(Realm.java:820)
                  at io.realm.Realm.createObject(Realm.java:801)
                  at theo.testing.realmapp.MainFragment$1$1.execute(MainFragment.java:58)
                  at io.realm.Realm.executeTransaction(Realm.java:1253)
                  at theo.testing.realmapp.MainFragment$1.run(MainFragment.java:52)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

I am using that version.

io.realm:realm-gradle-plugin:2.2.1

Any ideas how to fix this exception?

Thanks,

Theo.

like image 586
Theo Avatar asked Dec 08 '16 18:12

Theo


2 Answers

Yeah. Do what the exception tells you to do.

Instead of

    User user = realm.createObject(User.class);
            user.setFirstName("Theo");
            user.setLastName("Larsen");
            user.setId(UUID.randomUUID().toString());

Do

   User user = realm.createObject(User.class, UUID.randomUUID().toString());
           user.setFirstName("Theo");
           user.setLastName("Larsen");
           //user.setId(UUID.randomUUID().toString());

Reason

Primary keys are immutable since Realm 2.0.0, which means you cannot modify them after the object has been created. So pass it at the time of object creation.

like image 195
EpicPandaForce Avatar answered Nov 16 '22 03:11

EpicPandaForce


Use

User user = realm.createObject(User.class, primaryKeyValue);

add your primary key or generate using UUID.randomUUID().toString()

like image 38
Riyas PK Avatar answered Nov 16 '22 03:11

Riyas PK