【问题标题】:How to connect SQLiteOpenHelper class with MainActivity?如何将 SQLiteOpenHelper 类与 MainActivity 连接?
【发布时间】:2018-10-08 12:22:41
【问题描述】:

我创建了 3 个类(1. MainActivity、DBhelper 和 Student 类)。我是初学者,使用简单的代码,并且一直无法将 DBhelper 类与 MainActivity 连接起来。我认为一切正常,但是在单击“buttonAdd”后,我收到“我的应用程序已停止”的声明。 在 MainActivity 中,我只使用了 DBhelper 中的“loadStudents”和“addStudent”方法,因为即使是这些基本级别我也有问题。

应用程序的想法 --> 将新学生添加到 editText,删除它们等。我知道,最好使用 scrollList,但我只想知道如何首先使用 SQLite。

学生课 --> 我在“DBhelper 类”和“MainActivity”中使用它

public class Student {

private int studentID;
private String studentName;

public Student(int id, String studentName) { //konstruktor
    this.studentID = id;
    this.studentName = studentName;
}

public int getStudentID() {
    return studentID;
}

public void setStudentID(int studentID) {
    this.studentID = studentID;
}

public String getStudentName() {
    return studentName;
}

public void setStudentName(String studentName) {
    this.studentName = studentName;
}
}

DBhelper 类

public class DBhelper extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "studentDB.db";
public static final String TABLE_NAME = "student";
public static final String COLUMN_ID = "studentID";
public static final String COLUMN_NAME = "studentName";
//initialize the database

public DBhelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}


@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE " + TABLE_NAME + "("
            + COLUMN_ID + "INTEGER PRIMARYKEY,"
            + COLUMN_NAME + " TEXT " + ")");
}

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

public void addStudent(Student student) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(COLUMN_ID, student.getStudentID());
    values.put(COLUMN_NAME, student.getStudentName());
    db.insert(TABLE_NAME, null, values);
    db.close();
}

public String loadStudents() {
    String result = "";
    String query = "Select*FROM " + TABLE_NAME;
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(query, null);
    while (cursor.moveToNext()) {
        int result_0 = cursor.getInt(0);
        String result_1 = cursor.getString(1);
        result += String.valueOf(result_0) + " " + result_1 +
                System.getProperty("line.separator");
    }
    cursor.close();
    db.close();
    return result;
}

public Student findStudent(int ID, String studentName) {
    String query = "Select * FROM " + TABLE_NAME + "WHERE" + COLUMN_NAME + " 
= " + "'" + studentName + "'";
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(query, null);
    Student student = new Student(ID, studentName);
    if (cursor.moveToFirst()) {
        cursor.moveToFirst();
        student.setStudentID(Integer.parseInt(cursor.getString(0)));
        student.setStudentName(cursor.getString(1));
        cursor.close();
    } else {
        student = null;
    }
    db.close();
    return student;
}

public boolean deleteStudent(int ID, String studentName) {
    boolean result = false;
    String query = "Select*FROM" + TABLE_NAME + "WHERE" + COLUMN_ID + "= '" 
+ String.valueOf(ID) + "'";
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(query, null);
    Student student = new Student(ID, studentName);
    if (cursor.moveToFirst()) {
        student.setStudentID(Integer.parseInt(cursor.getString(0)));
        db.delete(TABLE_NAME, COLUMN_ID + "=?",
                new String[] {
            String.valueOf(student.getStudentID())
        });
        cursor.close();
        result = true;
    }
    db.close();
    return result;
}

public boolean updateStudent(int ID, String name) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues args = new ContentValues();
    args.put(COLUMN_ID, ID);
    args.put(COLUMN_NAME, name);
    return db.update(TABLE_NAME, args, COLUMN_ID + "=" + ID, null) > 0;
}
}

MainActivity

public class MainActivity extends AppCompatActivity {

Button buttonLoad;
Button buttonAdd;
Button buttonFind;
Button buttonDelete;
Button buttonUpdate;
TextView textViewStudents;
EditText editTextID;
EditText editTextName;
DBhelper myDB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    buttonLoad = (Button) findViewById(R.id.buttonLoad);
    buttonAdd = (Button) findViewById(R.id.buttonAdd);
    buttonFind = (Button) findViewById(R.id.buttonFind);
    buttonDelete = (Button) findViewById(R.id.buttonDelete);
    buttonUpdate = (Button) findViewById(R.id.buttonUpdate);
    textViewStudents = (TextView) findViewById(R.id.textViewStudents);
    editTextID = (EditText) findViewById(R.id.editTextID);
    editTextName = (EditText) findViewById(R.id.editTextName);
    myDB = new DBhelper(this);

    //load
    buttonLoad.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            textViewStudents.setText(myDB.loadStudents());
            editTextID.setText("");
            editTextName.setText("");
        }
    });

    buttonAdd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int id = Integer.parseInt(editTextID.getText().toString());
            String name = editTextName.getText().toString();
            Student student = new Student(id, name);
            myDB.addStudent(student);
            editTextID.setText("");
            editTextName.setText("");
        }
    });
}
// Maybe it will be better to use the methos under the onCreate method but I 
//don't know what should I write as a paramether instead of "view" when I 
//will use this method in the onCreate
//    public void addStudent() {
//        DBhelper myDB = new DBhelper(this);
//        int id = Integer.parseInt(editTextID.getText().toString());
//        String name = editTextName.getText().toString();
//        Student student = new Student(id, name);
//        myDB.addStudent(student);
//        editTextID.setText("");
//        editTextName.setText("");
//    }
}

【问题讨论】:

    标签: java android database sqlite


    【解决方案1】:

    loadStudents 方法中,您有 String query = "Select*FROM " + TABLE_NAME; 这将导致语法错误,因为 SELECT 和 * 和 * 和 FROM 之间没有空格。

    这应该是String query = "Select * FROM " + TABLE_NAME;

    您需要检查您的代码是否缺少空格,因为您省略了一个数字。

    • 列名和类型之间有一个空格,PRIMARY 和 KEY 之间也有一个空格,因此 studentID 将不是 rowid 列的别名,因此将为 null 而不是自动生成的唯一 ID。 **如果不解决此问题(不会导致错误),将导致 find/delete/update/Students 方法无法按预期工作。

    • 这里在 WHERE 关键字之前缺少另一个空格 TABLE_NAME + "WHERE"

    • 同样的初始错误Select*FROM 在 deleteStudent 方法中被复制。

    • 注意可能还有其他语法错误,以上只是通过代码视觉发现。

    我建议进行所有修改,然后删除应用程序的数据或卸载应用程序或增加分配给 DATABASE_VERSION 的值,然后重新运行应用程序。

    你也应该在'它停止工作'后检查日志,它会详细说明遇到的错误。

    附加

    以下是经过测试的代码,也包含一些建议,例如只使用学生的 id 来定位学生。

    DBhelper.java 类(为方便起见,使用了 DBhelper2 类):-

    public class DBhelper2 extends SQLiteOpenHelper { //<<<<<<<<<< Change DBhelper2 to DBhelper
    
        private static final int DATABASE_VERSION = 1;
        private static final String DATABASE_NAME = "studentDB.db";
        public static final String TABLE_NAME = "student";
        public static final String COLUMN_ID = "studentID";
        public static final String COLUMN_NAME = "studentName";    //initialize the database
    
        public DBhelper2(Context context) { //<<<<<<<<<< Change DBhelpe2 to DBhelper
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + TABLE_NAME + "("
                    + COLUMN_ID + " INTEGER PRIMARY KEY,"
                    + COLUMN_NAME + " TEXT " + ")");
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS contacts");
            onCreate(db);
        }
    
        public void addStudent(Student student) {
            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put(COLUMN_ID, student.getStudentID());
            values.put(COLUMN_NAME, student.getStudentName());
            db.insert(TABLE_NAME, null, values);
            db.close();
        }
    
        //<<<<<<<<<< ADDED add student allowing ID to be auto generated
        //!!!NOTE!!! ideally long should be used for ID and thus should return long not int
        //              won't be an issue with a small number of Students
        public int addNewStudent(String studentName) {
            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put(COLUMN_NAME,studentName);
            return (int) db.insert(TABLE_NAME,null,values);
        }
    
        public String loadStudents() {
            String result = "";
            String query = "Select * FROM " + TABLE_NAME; //<<<<<<<<<< ADDED SPACES
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery(query, null);
            while (cursor.moveToNext()) {
                int result_0 = cursor.getInt(0);
                String result_1 = cursor.getString(1);
                result += String.valueOf(result_0) + " " + result_1 +
                        System.getProperty("line.separator");
            }
            cursor.close();
            db.close();
            return result;
        }
    
        //<<<<<<<<<< Get all Students as an ArrayList of Student objects
        //<<<<<<<<<< Alternative to loadStudents
        public ArrayList<Student> getAllStudents() {
            ArrayList<Student> result = new ArrayList<>();
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
            while (csr.moveToNext()) {
                result.add(
                        new Student(
                                csr.getInt(csr.getColumnIndex(COLUMN_ID)),
                                csr.getString(csr.getColumnIndex(COLUMN_NAME)
                                )
                        )
                );
            }
            csr.close();
            db.close();
            return result;
        }
    
        public Student findStudent(int ID, String studentName) {
            String query = "Select * FROM " + TABLE_NAME + " WHERE " + COLUMN_NAME + //<<<<<<<<<< ADDED SPACES
                    " = " + "'" + studentName + "'"; //<<<<<<<<<< ADDED missing double quote
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery(query, null);
            Student student = new Student(ID, studentName);
            if (cursor.moveToFirst()) {
                cursor.moveToFirst(); //<<<<<<<<<< NOT NEEDED as already at first
                student.setStudentID(Integer.parseInt(cursor.getString(0)));
                student.setStudentName(cursor.getString(1));
                cursor.close();
            } else {
                student = null;
            }
            db.close();
            return student;
        }
    
        //<<<<<<<<<< alternative get student just by id
        //          uses the convenience query method rather than rawQuery
        //          recommended to use COLUMN NAMES not column offsets
        public Student findStudent(int studentID) {
            Student result = null;
            String whereclause = COLUMN_ID + "=?";
            String[] whereargs = new String[]{String.valueOf(studentID)};
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor csr = db.query(TABLE_NAME,null,whereclause,whereargs,null,null,null);
            if (csr.moveToFirst()) {
                result = new Student(
                        csr.getInt(csr.getColumnIndex(COLUMN_ID)),
                        csr.getString(csr.getColumnIndex(COLUMN_NAME)
                        )
                );
            }
            csr.close();
            db.close();
            return result;
        }
    
    
        //      Deleting just by id (see findStudent above) could/should be implemented
        public boolean deleteStudent(int ID, String studentName) {
            boolean result = false;
            String query = "Select * FROM " + TABLE_NAME + " WHERE " + COLUMN_ID + "= '" //<<<<<<<<<< ADDED SPACES
                    + String.valueOf(ID) + "'";
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery(query, null);
            Student student = new Student(ID, studentName);
            if (cursor.moveToFirst()) {
                student.setStudentID(Integer.parseInt(cursor.getString(0)));
                db.delete(TABLE_NAME, COLUMN_ID + "=?",
                        new String[] {
                                String.valueOf(student.getStudentID())
                        });
                cursor.close();
                result = true;
            }
            db.close();
            return result;
        }
    
        //      Updating just by id (see findStudent above) could/should be implemented
        public boolean updateStudent(int ID, String name) {
            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues args = new ContentValues();
            args.put(COLUMN_ID, ID);
            args.put(COLUMN_NAME, name);
            return db.update(TABLE_NAME, args, COLUMN_ID + "=" + ID, null) > 0;
        }
    }
    
    • 请参考以上代码中的cmets

    测试

    以下代码在活动的onCreate 方法中用于测试上述内容:-

        mDBStudents = new DBhelper2(this);
    
        //Delete all students for testing purposes only
        mDBStudents.getWritableDatabase().delete(DBhelper2.TABLE_NAME,null,null);
    
        // Load some data and test methods
        mDBStudents.addStudent(new Student(1,"Fred"));
        mDBStudents.addStudent(new Student(2,"Mary"));
        Log.d("STUDENTS",mDBStudents.loadStudents());
        Student a_student_found = mDBStudents.findStudent(1,"Fred");
        Log.d("STUDENTFOUND", a_student_found.getStudentName());
        mDBStudents.updateStudent(1,"Bert");
        a_student_found = mDBStudents.findStudent(1,"Bert");
        Log.d("STUDENtFOUND",a_student_found.getStudentName());
        mDBStudents.deleteStudent(2,"Mary");
        Log.d("STUDENTS",mDBStudents.loadStudents());
    
        //Test alternative suggested methods
        mDBStudents.addNewStudent("Harold");
        mDBStudents.addNewStudent("Susan");
        ArrayList<Student> all_students = mDBStudents.getAllStudents();
        boolean after_first_row = false;
        StringBuilder sb = new StringBuilder("Students are :-");
        for (Student s: mDBStudents.getAllStudents()) {
            sb.append("\n\t")
                    .append("Student ID is ")
                    .append(String.valueOf(s.getStudentID()))
                    .append(" Student name is ")
                    .append(s.getStudentName());
        }
        Log.d("STUDENTS",sb.toString());
        Student another = mDBStudents.findStudent(3);
        Log.d("STUDENT 3","Student with an ID of 3 is " + another.getStudentName());
    

    结果(在日志中)

    以下是测试产生的日志的输出:-

    2018-10-06 08:49:27.410 2382-2382/so52598847.so52598847 D/STUDENTS: 1 Fred
        2 Mary
    2018-10-06 08:49:27.411 2382-2382/so52598847.so52598847 D/STUDENTFOUND: Fred
    2018-10-06 08:49:27.418 2382-2382/so52598847.so52598847 D/STUDENtFOUND: Bert
    2018-10-06 08:49:27.426 2382-2382/so52598847.so52598847 D/STUDENTS: 1 Bert
    2018-10-06 08:49:27.444 2382-2382/so52598847.so52598847 D/STUDENTS: Students are :-
            Student ID is 1 Student name is Bert
            Student ID is 2 Student name is Harold
            Student ID is 3 Student name is Susan
    2018-10-06 08:49:27.445 2382-2382/so52598847.so52598847 D/STUDENT 3: Student with an ID of 3 is Susan
    

    结果符合预期。那是

    1. 学生 Fred 添加了 ID 1
    2. 添加了学生 Mary,ID 为 2
    3. 列出了学生 Fred 和 Mary。
    4. 学生 1 (Fred) 已更新为 Bert。
    5. 找到学生 1(现为 Bert)
    6. 学生 Bert 已列出。
    7. 学生 2(玛丽)被删除。
    8. 添加了学生 Harold 和 Susan(使用替代方法,即 addNewStudent)。
    9. 所有学生在通过替代 getAllStudents 方法获取后被列出。
    10. 学生 3 由替代 findStudent 方法检索(仅通过 id,因此名称更改(例如 Fred 到 Bert)不会影响获取学生)并列出。

    【讨论】:

    • 太棒了:) ---> 1。 “addNewStudent 方法”- 它返回“int”,因为该学生的 ID 将自动生成? --->2。 “测试”开始 -----> mDBStudents.getWritableDatabase().delete(DBhelper.TABLE_NAME,null, null); --> “删除”方法是否来自 SQLite 类库并删除所有数据? ---> 3. 想看日志时应该一直打开应用程序,还是有其他按钮可以更快地查看日志? ---->4。如果我必须写上我想上传另一个名字的名字,为什么我应该只为学生ID paraether更改“updateStudent”方法?
    • ---> 5 我添加了 2 个学生第一个 final ArrayList myArrayList = mDBStudents.getAllStudents(); StringBuilder sb = new StringBuilder("学生是 :-"); for (学生s: mDBStudents.getAllStudents()) { sb.append("\n\t") .append(myArrayList.get(1)); } Log.d("学生",sb.toString()); -----> 我尝试使用 ArrayAdapter 在 ListView 中显示学生的姓名,但它不起作用,所以我返回 Log.d,我只看到我们在 ex 时得到的有趣字母:我们想显示“字符串" 消息,但我们写了 "int" 而忘记解析它
    • Q1 column_name INTEGER PRIMARY KEY 是特殊的(带或不带)AUTOINCREMENT 关键字,表示该列是rowid 列的别名,它是(如果未指定值)自动生成的唯一标识符,范围为​​ 1 - 9223372036854775807(实际上应该是 long 而不是 int)。因此可用于唯一标识行,并且通常是访问行的最有效方式(将其视为超级主键)。查看SQLite Autoincrement
    • Q2删除方法,如果不使用where子句,将删除所有行(更新方法也是)。
    • Q3 因为当您使用 ArrayList&lt;Student&gt; 时,适配器使用 Student 的 toString 方法,如果未覆盖该方法,则使用默认对象 toString 方法并以字符串形式返回对象内存位置/地址。指针因此@???????? (@后面是有趣的数字)。解决方法是 a) 覆盖 Student 的 toString 方法,或者,b) 使用自定义 ArrayAdapter,c) 使用光标适配器 (SimpleCursorAdapter)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    相关资源
    最近更新 更多