我在一个Android应用程序中设置了一个SQLite数据库,但是为了专注于immeidate问题,我只会引用Users
表。在DatabaseContract
中,Users
表定义为:
public final class DatabaseContract {
private DatabaseContract() {}
public static class Users implements BaseColumns {
public static final String TABLE_NAME = "users";
public static final String COLUMN_USER_ID = "_id";
public static final String COLUMN_USER_NAME = "user_name";
public static final String COLUMN_PASSWORD = "password";
public static final String COLUMN_EMAIL = "email";
public static final String COLUMN_DISPLAY_NAME = "display_name";
}
...rest of tables in db
}
在DatabaseHelper
类中,这是Users
表:
private static final String SQL_CREATE_USERS_TABLE =
"CREATE TABLE " + DatabaseContract.Users.TABLE_NAME + " (" +
DatabaseContract.Users.COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
DatabaseContract.Users.COLUMN_USER_NAME + " TEXT NOT NULL, " +
DatabaseContract.Users.COLUMN_PASSWORD + " TEXT NOT NULL, " +
DatabaseContract.Users.COLUMN_EMAIL + " TEXT, " +
DatabaseContract.Users.COLUMN_DISPLAY_NAME + " TEXT)";
在我的AddUserActivity
类中运行这个方法addUserToDatabase(String name, String email, String password, String displayName)
,它似乎可以工作,但是我希望从Users
表中获取自动生成的'id',然后在这里检索'id':
// Check if the insertion was successful
if (newRowId != -1) {
// User was added successfully
Toast.makeText(this, "User added successfully!", Toast.LENGTH_SHORT).show();
// Get the user_id of the newly added user
int user_id = getUserId(db, name);
...
下面是getUserId(db, name)
方法:
private int getUserId(SQLiteDatabase db, String name) {
int user_id = -1; // Default value if no user is found
// Define the columns you want to retrieve
String[] projection = {
DatabaseContract.Users.COLUMN_USER_ID
};
// Define the selection based on the user name
String selection = DatabaseContract.Users.COLUMN_USER_NAME + " = ?";
String[] selectionArgs = { name };
// Define the sort order (if needed)
String sortOrder = null;
Cursor cursor = db.query(
DatabaseContract.Users.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
if (cursor.moveToFirst()) {
// Get the user_id from the cursor
int usersIdIndex = cursor.getColumnIndexOrThrow(DatabaseContract.Users.COLUMN_USER_ID);
user_id = cursor.getInt(usersIdIndex);
}
// Close the cursor (don't close the database here)
cursor.close();
return user_id;
}
然后我创建一个Intent,将此数据传递到WelcomeActivity
页面:
...
// Create an Intent to navigate to WelcomeActivity
Intent intent = new Intent(AddUserActivity.this, WelcomeActivity.class);
int testNumber = 777;
// Pass user data and user_id as extras in the Intent
intent.putExtra("USER_ID", user_id);//testNumber
intent.putExtra("USER_NAME", name);
intent.putExtra("USER_EMAIL", email);
intent.putExtra("USER_DISPLAY_NAME", displayName);
// Start the WelcomeActivity
startActivity(intent);
// Close this activity
finish();
此时,程序崩溃并出现以下错误:
E/SQLiteLog: (1) no such column: _id in "SELECT _id FROM users WHERE user_name = ?"
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.enetapplications.songtracker, PID: 5937
android.database.sqlite.SQLiteException: no such column: _id (code 1 SQLITE_ERROR[1]): , while compiling: SELECT _id FROM users WHERE user_name = ?
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1478)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:916)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:63)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:2088)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1935)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1806)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1974)
at com.enetapplications.songtracker.AddUserActivity.getUserId(AddUserActivity.java:124)
at com.enetapplications.songtracker.AddUserActivity.addUserToDatabase(AddUserActivity.java:84)
at com.enetapplications.songtracker.AddUserActivity.access$400(AddUserActivity.java:20)
at com.enetapplications.songtracker.AddUserActivity$1.onClick(AddUserActivity.java:58)
at android.view.View.performClick(View.java:7792)
at android.widget.TextView.performClick(TextView.java:16112)
at android.view.View.performClickInternal(View.java:7769)
at android.view.View.access$3800(View.java:910)
at android.view.View$PerformClick.run(View.java:30218)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
我是SQLite的新手,因此适应了SQLite -但对标准SQL/MySQL非常熟悉。我倾向于将Users
表的键命名为user_id
,但SQLite标准似乎将表的键保留为_id
提前感谢您的审查和评论!
最好的,布莱恩
2条答案
按热度按时间brjng4g31#
这是一个非常奇怪的问题
不,它不是,它应该是这样的。不像Activities等,onCreate经常被称为数据库是一个持久性实体,否则它将是无用的(至少对于它的预期目的)。无论设备或应用程序的状态如何,都需要保留存储在其中的数据(除非当用户选择不再需要数据时删除)。此外,当更新应用程序时,可能必须保留数据(这可能涉及或可能不涉及对数据库模式的更改)。
简单地说,
onCreate
方法反映了这样一个事实,即只有在创建数据库时才调用它。如果需要更改,那么就是
onUpdate
(或很少使用的onDownGrade
)发挥作用的时候。这两者都是由数据库版本驱动的,就像在构造一个扩展SQLiteOpenHelper的类时传递的那样。我一直收到错误,无法撤消原始的数据库配置。
根据评论。SQLiteOpenHelper的 (因此也是一个扩展SQLiteOpenHelper的类)
onCreate
方法在数据库的生存期内只被调用一次。因此,对代码的任何更改(通常是在最初创建表的地方)将不会反映为代码不运行。如果在发布之前开发应用程序,并且数据库所持有的数据可能会丢失,那么所需的就是删除数据库。这可以通过卸载App来实现。由于没有数据库,
onCreate
将被调用。如果应用程序已经发布,或者需要保留数据,则可以使用数据库版本和
onUpdate
方法从较低版本迁移数据库。解决方案是更改数据库名称-只需添加“2”:private static final String DATABASE_NAME =“song_tracker2.db”;
这是因为您现在已经指定了另一个数据库作为要使用的数据库,因此
onCreate
方法已经被调用,并且模式与预期的一样。但是,原始数据库仍然存在,并浪费一些存储空间。演示迁移
以下是如何使用
onUpgrade
方法来引入更改的工作演示(即使只是卸载应用程序就足够了,因为您很乐意使用另一个数据库)。演示所做的是展示如何使用
onUpgrade
方法保留数据。它展示了一种基本的方法,几乎可以将任何更改应用于表。在本例中,将主键的列名从users_id更改为_id。因此,请考虑以下DatabaseHelper类(显然您将拥有自己的类):
上述重要因素包括:
onUpgrade
方法中的编码,如果从小于版本2的版本升级到版本2,将调用migrateDBFromVersion1ToVersion2
migrateDBFromVersion1ToVersion2
中遵循的基本过程是:onCreate
方法中,以便新的应用程序安装具有相同的模式)logSchema
方法类似于getTableMetaData
方法。然后,DatabaseContract类作为驱动程序发挥作用,它被更改为包括数据库名称和版本,如下所示:-
显然,在一个活动中需要做一些事情,所以:
因此,这将:
结果/测试1 -应用程序在版本1的新鲜安装
日志包括:
因此,用户表具有
结果/测试2-应用程序刚刚使用更改的代码重新启动
对于此测试,更改了3行代码:
public static final int DATABASE_VERSION = 2;
(为1)public static final String COLUMN_USER_ID = "_id"; /* Version 2 */
(已注解掉)//public static final String COLUMN_USER_ID = "users_id"; /* Version 1 */
(未注解)日志现在包括:
即:-
*_id,根据变更
DROP TABLE original_users
的执行被注解掉了,现在不需要的original_users表仍然存在,它有users_id列,而不是新的**_id**列。结果/测试3全新安装-版本2代码
该应用程序被禁用,然后运行日志包括:-
jrcvhitl2#
这是一个非常奇怪的问题-在应用程序开发的早期,在我的
Users
表中,我的键是users_id
,但后来更改了它(在DatabaseHelper
和DatabaseContract
中更改为user_id
)。最后,我能够“看到”db Meta数据,意识到所有这些修改都没有做任何事情:输出一致:
D Column Name: users_id
其他尝试包括更改版本:
private static final int DATABASE_VERSION = 3;
也没做什么。解决方案是更改数据库名称-仅添加“2”:
private static final String DATABASE_NAME = "song_tracker2.db";
解决了问题。