简体   繁体   中英

Android Studio - Room Persistence Library - Ensuring that the Primary Key a user enters is unique before inserting into the database

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.

In my sample application, I'm allowing the user to enter very basic student information:

在此处输入图片说明

I've created the following three necessary components for the database:

1. Entity (Student)

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;
    }
}

2. Data Access Object API

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<Student> 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<Student> findStudentByName(String first, String last);
}

3. Database

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();
}

For reference, here's the main activity:

Main Activity

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();
    }
}

What I want to do

You'll notice in the entity class that I've included the annotation @PrimaryKey(autogenerate = true) . This designates the id field as the primary key of the Student table, and the autogenerate 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 ADD button twice, for example.

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.

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 ADD 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).

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?

您可以尝试在Insert方法中定义OnConflictStrategy来处理错误,请检查此链接

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM