title: Android Studio - Room Persistence Library - Ensuring that the Primary Key a user enters is unique before inserting into the database
body: <p>I'm learning how to use the Room Persistence Library in Android Studio, which is basically a layer of abstraction on top of SQLite that makes databasing easier.</p>
  
  <p>In my sample application, I'm allowing the user to enter very basic student information:</p>
  
  <p><a href="https://i.stack.imgur.com/B52qR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/B52qR.png" alt="enter image description here"></a></p>
  
  <p>I've created the following three necessary components for the database:</p>
  
  <p><strong>1. Entity (Student)</strong></p>
  
  <pre><code>package com.aleks.firstdatabaseproject;
  
  import android.arch.persistence.room.ColumnInfo;
  import android.arch.persistence.room.Entity;
  import android.arch.persistence.room.PrimaryKey;
  
  /* This is one entity that will be stored in our database. A Student has a
   * unique ID, a first name, and a last name.
   */
  
  @Entity
  public class Student {
  
      @PrimaryKey(autoGenerate = true)
      private int id;
  
      @ColumnInfo(name = "first_name")
      private String firstName;
  
      @ColumnInfo(name = "last_name")
      private String lastName;
  
      @ColumnInfo(name = "email")
      private String email;
  
      @ColumnInfo(name="notes")
      private String notes;
  
      public Student() { this("", "", "", ""); }
  
      public Student(String firstName, String lastName, String email, String notes) {
          setFirstName(firstName);
          setLastName(lastName);
          setEmail(email);
          setNotes(notes);
      }
  
      public void setId(int id){ this.id = id; }
  
      public void setFirstName(String firstName) { this.firstName = firstName; }
  
      public void setLastName(String lastName) { this.lastName = lastName; }
  
      public int getId() { return this.id; }
  
      public String getFirstName() { return this.firstName; }
  
      public String getLastName() { return this.lastName; }
  
      public String getNotes() { return notes; }
  
      public void setNotes(String notes) { this.notes = notes; }
  
      public String getEmail() {
          return email;
      }
  
      public void setEmail(String email) {
          this.email = email;
      }
  }
  </code></pre>
  
  <p><strong>2. Data Access Object API</strong></p>
  
  <pre><code>package com.aleks.firstdatabaseproject;
  
  import android.arch.persistence.room.Dao;
  import android.arch.persistence.room.Delete;
  import android.arch.persistence.room.Insert;
  import android.arch.persistence.room.Query;
  
  import com.aleks.firstdatabaseproject.Student;
  
  import java.util.List;
  
  /* A Data Access Object (DAO) provides an abstracted interface that allows
   * a user program to request information from the database. The DAO provides
   * methods for insertion, deletion, and querying in the database.
   */
  
  @Dao
  public interface StudentDAO {
  
      @Insert
      void addStudent(Student student);
  
      @Delete
      void removeStudent(Student student);
  
      @Query("SELECT * FROM Student")
      List&lt;Student&gt; getAllStudents();
  
      @Query("SELECT * FROM Student WHERE id IS :studentID")
      Student findStudentByID(int studentID);
  
      @Query("SELECT * FROM Student WHERE first_name LIKE :first AND last_name LIKE :last")
      List&lt;Student&gt; findStudentByName(String first, String last);
  }
  </code></pre>
  
  <p><strong>3. Database</strong></p>
  
  <pre><code>package com.aleks.firstdatabaseproject;
  
  import android.arch.persistence.room.Database;
  import android.arch.persistence.room.RoomDatabase;
  
  import com.aleks.firstdatabaseproject.Student;
  import com.aleks.firstdatabaseproject.StudentDAO;
  
  @Database(entities = {Student.class}, version = 1)
  public abstract class StudentDatabase extends RoomDatabase {
  
      /* Used by apps to get the data access object from the database */
      public abstract StudentDAO studentDAO();
  }
  </code></pre>
  
  <p>For reference, here's the main activity:</p>
  
  <p><strong>Main Activity</strong></p>
  
  <pre><code>package com.aleks.firstdatabaseproject;
  
  import android.arch.persistence.room.Room;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.TextView;
  
  import org.w3c.dom.Text;
  
  import java.util.List;
  
  public class MainActivity extends AppCompatActivity {
  
      private static StudentDatabase mDatabase;
      private StudentDAO mStudentDAO;
      private TextView mFirstName;
      private TextView mLastName;
      private TextView mId;
      private TextView mEmail;
      private TextView mNotes;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          mDatabase = Room.databaseBuilder(getApplicationContext(),
                  StudentDatabase.class, "database-name").build();
          mStudentDAO = mDatabase.studentDAO();
  
          mFirstName = (TextView) findViewById(R.id.editText_firstName);
          mLastName = (TextView) findViewById(R.id.editText_lastName);
          mId = (TextView) findViewById(R.id.editText_id);
          mEmail = (TextView) findViewById(R.id.editText_email);
          mNotes = (TextView) findViewById(R.id.editText_notes);
      }
  
      /* Uses the information in the app's main fields to build and
       * return a new Student object for use by other methods.
       */
      public Student buildStudentFromFields() {
          String firstName = mFirstName.getText().toString();
          String lastName = mLastName.getText().toString();
          String email = mEmail.getText().toString();
          String notes = mNotes.getText().toString();
          return new Student(firstName, lastName, email, notes);
      }
  
      /* Called when the user clicks the "ADD" button. Inserts
       * the given Student into the database.
       */
      public void addStudent(View view) {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  mStudentDAO.addStudent(buildStudentFromFields());
              }
          }).start();
      }
  
      /* Called when the user clicks the "REMOVE" button. Removes
       * the given Student from the database.
       */
      public void removeStudent(View view) {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  mStudentDAO.removeStudent(buildStudentFromFields());
              }
          }).start();
      }
  
      /* Called when the user clicks the "FIND" button. Returns
       * information about the given Student from the database.
       */
      public void findStudent(View view) {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  Student student = mStudentDAO.findStudentByID(Integer.parseInt(mId.getText().toString()));
              }
          }).start();
      }
  }
  </code></pre>
  
  <hr>
  
  <p><strong>What I want to do</strong></p>
  
  <p>You'll notice in the entity class that I've included the annotation <code>@PrimaryKey(autogenerate = true)</code>. This designates the <code>id</code> field as the primary key of the <code>Student</code> table, and the <code>autogenerate</code> option forces the database to generate its own primary keys instead of the user consciously remembering to pass in a unique key. But users are prone to error, and they may accidentally hit the <code>ADD</code> button twice, for example.</p>
  
  <p>Here's the problem: I want to allow the user to pass in their own custom Student ID like I've shown in the screenshot, but that poses a problem if the user attempts (illegally) to enter the same Student ID twice—the app crashes in that case.</p>
  
  <p>One potential solution is to keep a set/hash table of all IDs the user has entered so far and make sure that what they've entered is unique before trying to <code>ADD</code> the Student to the database. But that just takes up more memory than seems necessary (not a lot for such a small app, but it doesn't seem reasonable to store that extra "junk" info).</p>
  
  <p><strong>Is there any way I can account for duplicate primary keys to prevent the app from crashing when a user accidentally enters the same Student ID twice?</strong></p>