1

作成したテーブルにデータを挿入しようとしています。私はこのクラスを持っています:

public class DataBase extends SQLiteOpenHelper {
private static final String DB_NAME = "db_mydatabase";
private static final int DB_VERSION = 1;

private static final String TBL_USERS = "users";
private static final String TBL_USERSE_CREATE = "CREATE TABLE IF NOT EXISTS "
                            + TBL_USERS + "(id integer PRIMARY KEY AUTOINCREMENT, "
                            + "usr varchar(128) NOT NULL UNIQUE, psw varchar(512));";

public DataBase(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

public List<String> GetUsersList() {
    List<String> users = new ArrayList<String>();
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor c = db.rawQuery("SELECT id, usr FROM " + TBL_USERS, null);
    if (c != null ) {
        if  (c.moveToFirst()) {
            do {
                String firstName = c.getString(c.getColumnIndex("USR"));
                users.add(firstName);
                } while (c.moveToNext());
        }
    }
    return users;
}

public void CreateNewUser(String username, String password) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL("INSERT INTO " + TBL_USERS + " (usr, psw) VALUES ('" + username + "', '" + password + "')");
            //If I comment this line, it doesn't crashes anymore, but I don't see why
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(TBL_USERSE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + TBL_USERS);
    onCreate(db);
}

}

したがって、REGISTER ボタンを押すと、EditText からのユーザー名とパスワードが CreateNewUser に送信されます。私の Activity クラスは次のようになります。

public class RegisterActivity extends Activity {
List<String> values;
DataBase dtb;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.register);

    ListView listView = (ListView) findViewById(R.id.listView1);

    dtb = new DataBase(MainActivity.MainContext);
    values = dtb.GetUsersList();

    listView.setAdapter(new ArrayAdapter<String>(MainActivity.MainContext, R.layout.listitem, values));

    Button Create = (Button) findViewById(R.id.Create);
    Create.setOnClickListener(new View.OnClickListener() {
       public void onClick(View arg0) {
           EditText username = (EditText)findViewById(R.id.Username);
           EditText password = (EditText)findViewById(R.id.Password);
           if (username.getText().length()>0 && password.getText().length()>0) {
               if (values.indexOf(username.getText())<0) {
                   dtb.CreateNewUser(username.getText().toString(), password.getText().toString());
                   values = dtb.GetUsersList();
               }
           }
       }
    });
}

}

私は SQLite プログラマーとして初心者ですが、このわかりやすい重大なエラーとクラッシュが発生します。

> **04-24 12:30:51.340: E/CursorWindow(7986): フィールド スロット 0、-1 の不正な要求。numRows = 1、numColumns = 2** 04-24 12:30:51.350:
> D/AndroidRuntime(7986): VM 04-24 12:30:51.350 をシャットダウンしています:
> W/dalvikvm(7986): threadid=3: キャッチされない例外で終了するスレッド
> (グループ = 0x4001b188) 04-24 12:30:51.350: E/AndroidRuntime (7986):
> キャッチされていないハンドラー: キャッチされていない例外が原因で、スレッド メインが終了します
> **04-24 12:30:51.380: E/AndroidRuntime(7986): java.lang.IllegalStateException: 行 0 からフィールド スロットを取得 col -1
> 失敗しました** 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> android.database.CursorWindow.getString_native(ネイティブメソッド) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.database.CursorWindow.getString(CursorWindow.java:329) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:49)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> com.bma.myagenda.DataBase.GetUsersList(DataBase.java:32) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> com.bma.myagenda.RegisterActivity$1.onClick(RegisterActivity.java:46)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.View.performClick(View.java:2364) 04-24 12:30:51.380:
> E/AndroidRuntime(7986): で
> android.view.View.onTouchEvent(View.java:4179) 04-24 12:30:51.380:
> E/AndroidRuntime(7986): で
> android.widget.TextView.onTouchEvent(TextView.java:6541) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.View.dispatchTouchEvent(View.java:3709) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> android.app.Activity.dispatchTouchEvent(Activity.java:2061) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> android.view.ViewRoot.handleMessage(ViewRoot.java:1691) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.os.Handler.dispatchMessage(Handler.java:99) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> android.os.Looper.loop(Looper.java:123) 04-24 12:30:51.380:
> E/AndroidRuntime(7986): で
> android.app.ActivityThread.main(ActivityThread.java:4363) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> java.lang.reflect.Method.invokeNative(ネイティブメソッド) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> java.lang.reflect.Method.invoke(Method.java:521) 04-24 12:30:51.380:
> E/AndroidRuntime(7986): で
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
> 04-24 12:30:51.380: E/AndroidRuntime(7986): で
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 04-24
> 12:30:51.380: E/AndroidRuntime(7986): で
> dalvik.system.NativeStart.main(ネイティブメソッド)
4

3 に答える 3

1

挿入コードを次のように置き換えてみてください。

public void CreateNewUser(String username, String password) {
    SQLiteDatabase db = this.getWritableDatabase();

ContentValues initialValues = new ContentValues();
initialValues.put(usr, username);
initialValues.put(psw, password);

db.insert(TBL_USERS, null, initialValues);
}
于 2012-04-27T20:09:52.217 に答える
1

変化する

String firstName = c.getString(c.getColumnIndex("USR"));

String firstName = c.getString(1);

エラー

CursorWindow(7986): Bad request for field slot 0,-1. numRows = 1, numColumns = 2
...java.lang.IllegalStateException: get field slot from row 0 col -1 failed

は、 a の最初の行でインデックス -1 の列を要求することを意味しますCursor。からデータを要求するコードの唯一の部分Cursorc.getString(columnIndex). つまり、そこにある columnIndex は-1. ドキュメントを読むと、次のCursor.getColumnIndexことがわかります。

指定された列名のゼロから始まるインデックスを返します。列が存在しない場合は -1 を返します。

という名前の列がないことを意味します"USR"。テーブル定義を見ると、名前が付けられていることがわかります"usr"。エラーを修正するには、次のことができます

String firstName = c.getString(c.getColumnIndex("usr"));

ただし (これはオプションであり、エラーにつながる可能性があります): をリクエストしたのでCursor、is 列であり、is 列でSELECT id, usr FROM ..あることが保証されているため、 を直接使用することができます。id0usr1Cursor1

あなたが改善できる他のものもあります:

if (c != null ) {
    while(c.moveToNext()) {
        String firstName = c.getString(1);
        users.add(firstName);
    }
    c.close();
}

a)if () do {} while ()を単純なものに単純化できますwhile() {}
b)必要がなくなったらを閉じるCursor必要があります。そのようにして、少なくとも警告を防ぎます。

INSERTの bindArgs バージョンを使用して、エラー/インジェクション攻撃に対する保存も行う必要がありますexecSQL。ユーザー名に a を入力してみると、'そのようにクラッシュすることがわかります。bindArgs を使用すると、'.

db.execSQL("INSERT INTO " + TBL_USERS + " (usr, psw) VALUES (?, ?)", new String[]{ username, password });

この行にコメントすると、クラッシュしなくなりましたが、理由がわかりません

これは、Cursorが空で、エラーの原因となったコードに到達していないためです。

最後にもう 1 つ: varchar(128)SQLite では次の理由から効果がありません。

型名に続く括弧内の数値引数 (例: "VARCHAR(255)") は、SQLite によって無視されることに注意してください。SQLite は、文字列、BLOB、または数値の長さに長さ制限を課しません。ソース

于 2012-04-27T20:10:07.450 に答える
1

変化する:

String firstName = c.getString(c.getColumnIndex("USR"));

に:

String firstName = c.getString(c.getColumnIndex("usr"));  //USR != usr
于 2012-04-27T20:14:02.660 に答える