Есть ли способ сделать метод проверки, если в базе данных существуют уникальные данные? - PullRequest
0 голосов
/ 01 июня 2019

Моя цель - создать метод в Android Studio, который проверяет, существует ли в моей базе данных существующее имя пользователя (уникальное). Но моя проблема в том, что я понятия не имею, почему мой реализованный код не работает и возвращает ошибку в logcat. Приложение не падает, однако.

На самом деле я пытался реализовать 2 разных метода. Первый заключается в том, чтобы поместить все выбранные существующие имена пользователей из базы данных в arraylist и использовать метод ArrayList.contains (username), чтобы проверить, содержит ли arraylist похожее имя пользователя.

Другой метод, который я попытался использовать, - это выбрать имя пользователя в базе данных, которое совпадает с моим введенным именем пользователя, и посмотреть, совпадают ли они. (Может показаться странным, но я покажу вам код).

MainActivity.java

DatabaseHelper mydb = new DatabaseHelper(this, "MyUsers", null, 1);

UserInfo userInfo = new UserInfo(tvUsername.getText().toString(), etEnterPassword.getText().toString());

            if (mydb.existingUsername(tvUsername.getText().toString()) == false) {
                mydb.insertTable(userInfo);
                Intent intent = new Intent(MainActivity.this, Lobby.class);
                intent.putExtra("username", userInfo.getUsername());
                startActivity(intent);
            } else {
                // some code
            }

DatabaseHelper.java

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("create table " + TABLE_NAME + "(" +
            COLUMN_ID + " integer primary key autoincrement, " +
            COLUMN_USERNAME + " text not null unique, " +
            COLUMN_PASSWORD + " text)");
}

// Method 1 (Commented out)
public ArrayList<UserInfo> existingUsername() {
    UserInfo userInfo;
    ArrayList<UserInfo> userArray = new ArrayList<UserInfo>();
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT " + COLUMN_USERNAME + " FROM " + TABLE_NAME, null);
    cursor.moveToFirst();
    while (!cursor.isAfterLast()) {
        userInfo = new UserInfo(cursor.getString(cursor.getColumnIndex(COLUMN_USERNAME)));
        userArray.add(userInfo);
        cursor.moveToNext();
    }
    return userArray;
}

// Method 2 (Currently in use)
public boolean existingUsername(String username) {
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT " + COLUMN_USERNAME + " FROM " + TABLE_NAME + " WHERE " + COLUMN_USERNAME + " = ?", new String[]{username});
    cursor.moveToFirst();
    while (!cursor.isAfterLast()) {

        if (cursor.getString(cursor.getColumnIndex(COLUMN_USERNAME)) == username) {
            return true;
        } else {
            cursor.moveToNext();
        }
    }
    return false;
}

Ожидаемые результаты:

Я хочу, чтобы он проверил, существует ли введенное мной "имя пользователя" в базе данных или нет. Если нет, запустите оператор «if» и перейдите к следующему действию. Если да, запустите оператор "else".

Фактические результаты:

Однако оказывается, что код продолжает выполнять оператор if и выполняет следующее действие независимо от того, существует ли введенное имя пользователя в базе данных или нет. Если введенное имя пользователя уже существует в базе данных, это дает мне эту ошибку в logcat.

Logcat

019-06-01 14:06:19.774 27199-27199/com.karimun.myapplication E/SQLiteDatabase: Error inserting password=232323 username=Igor
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: users.username (code 2067 SQLITE_CONSTRAINT_UNIQUE)
    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
    at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1564)
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1433)
    at com.karimun.myapplication.DatabaseHelper.insertTable(DatabaseHelper.java:70)
    at com.karimun.myapplication.MainActivity$2.onClick(MainActivity.java:58)
    at android.view.View.performClick(View.java:6597)
    at android.view.View.performClickInternal(View.java:6574)
    at android.view.View.access$3100(View.java:778)
    at android.view.View$PerformClick.run(View.java:25885)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Ответы [ 3 ]

1 голос
/ 01 июня 2019

Вы не показываете свой метод insertTable(userInfo), но если вы используете (при условии, что вы используете метод execSQL для вставки), а затем используете INSERT OR IGNORE вместо INSERT, дубликат будет игнорироваться .

Однако, если вместо этого вы используете метод insert (он эффективно использует INSERT OR IGNORE). Возвращает rowid длинной вставленной строки, если строка не была вставлена, возвращается -1. Поэтому проверка возвращаемого значения скажет вам, что по какой-то причине (вероятно, дубликату) строка не была вставлена ​​(что сводит на нет необходимость предварительной проверки и связанных накладных расходов).

  • Поскольку вы определили столбцы идентификаторов, используя integer primary key autoincrement, этот столбец является псевдонимом столбца rowid (поэтому значение rowid будет таким же, как столбец идентификатора).

Ниже приведен код, каким он может быть, основанный на том, что можно почерпнуть из доступного кода.

public long insertTable(UserInfo userInfo) {

    ContentValues cv = new ContentValues();
    SQliteDatabase db = this.getWritableDatabase();
    cv.put(COLUMN_USERNAME,userInfo.getUserName());
    cv.put(COLUMN_PASSWORD,userInfo.getPassword());
    return db.insert(TABLE_NAME,null,cv);
}
  • Обратите внимание, поскольку у него такое же имя и подпись, это должно заменить существующий метод или быть названным по-другому.
  • Примечание getPassword может быть неправильным методом, используемым для получения значения пароля из UserInfo

Код в MainActivity.java может быть следующим: -

        UserInfo userInfo = new UserInfo(tvUsername.getText().toString(), etEnterPassword.getText().toString());

        long id;
        if (id = mydb.insertTable(userInfo) > 0) {
            Intent intent = new Intent(MainActivity.this, Lobby.class);
            intent.putExtra("username", userInfo.getUsername());
            intent.putExtra("userid",id); //<<<<<<<<<< you now have the id
            startActivity(intent);
        } else {
            // some code because user was not added
        }
  • Обратите внимание, что приведенный выше код является принципиальным и может содержать некоторые ошибки, поскольку он не был протестирован или запущен.
0 голосов
/ 01 июня 2019

Вы должны позволить SQL сделать всю работу за вас:

Select count(*) from sometable where username = @username

Это вернет количество записей, которые содержат @username.Если число равно 0, то имя пользователя не существует в таблице.Если это 1, то имя пользователя существует и является уникальным.Если оно больше 1, то имя пользователя существует и не является уникальным.

0 голосов
/ 01 июня 2019

У вас неправильное сравнение

cursor.getString(cursor.getColumnIndex(COLUMN_USERNAME)) == username

Это приводит к тому, что ваша программа продолжает вставлять, даже если имя пользователя уже существует.

Измените на equals() для правильного сравнения строк. Не используйте == для сравнения строк (и объектов в целом)

username.equals(cursor.getString(cursor.getColumnIndex(COLUMN_USERNAME)))

, если username не равно нулю

или

Objects.equals(username, cursor.getString(cursor.getColumnIndex(COLUMN_USERNAME)))
...