Java 从未调用SQLiteHelper的onCreate()方法
我正在使用SQLite在android中创建一个数据库 我编写代码是为了在onCreate()方法中创建一个名为Java 从未调用SQLiteHelper的onCreate()方法,java,android,android-sqlite,oncreate,sqliteopenhelper,Java,Android,Android Sqlite,Oncreate,Sqliteopenhelper,我正在使用SQLite在android中创建一个数据库 我编写代码是为了在onCreate()方法中创建一个名为products的表 然后,当我调用add()方法向表中添加一些值时,我得到一个错误,即没有名为products的表 这是我的SQLiteHelper类: public class MySQLiteHelper extends SQLiteOpenHelper { //variable declarations and some code ... @Over
products
的表
然后,当我调用add()方法向表中添加一些值时,我得到一个错误,即没有名为products
的表
这是我的SQLiteHelper类:
public class MySQLiteHelper extends SQLiteOpenHelper {
//variable declarations and some code
...
@Override
public void onCreate(SQLiteDatabase db) {
// SQL statement to create a products table
String CREATE_PRODUCTS_TABLE = "CREATE TABLE "+TABLE_NAME+ " ( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"url TEXT, " +
"title TEXT, " +
"price INTEGER );";
// create products table
db.execSQL(CREATE_PRODUCTS_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
// Create tables again
onCreate(db);
}
void add(String url, String title, String price) {
this.url = url;
this.title = title;
this.price = price;
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. create ContentValues to add key "column"/value
ContentValues values = new ContentValues();
values.put(KEY_URL, url);
values.put(KEY_TITLE, title);
values.put(KEY_PRICE, price);
// 3. insert
db.insert(TABLE_NAME, // table
null, //nullColumnHack
values); // key/value -> keys = column names/ values = column values
// 4. close
db.close();
}
我从一个类似的问题中读到,onCreate()不是构造函数,只有当数据库不存在时才会调用它,但在我的例子中,数据库也不存在,所以为什么不调用它呢
我还了解到我们需要调用getWritableDatabase()
或getReadableDatabase()
但我不确定在我的代码中在哪里进行这样的调用
我试图将onCreate()
中的“table creating code”放入我的add()
方法中。在第一次运行中,我没有得到任何结果,但从下一次开始,我不断得到一个错误,即“表已经存在”
现在,在调用我的add()
方法插入一些值之前,如何确保只正确创建一次表。需要帮忙吗
编辑:
我的日志如下:
03-07 00:59:22.684 2107-2147/com.example.nikhil.amazon1 W/EGL_emulation﹕ eglSurfaceAttrib not implemented
03-07 00:59:22.684 2107-2147/com.example.nikhil.amazon1 W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa5683060, error=EGL_SUCCESS
03-07 00:59:24.922 2107-2120/com.example.nikhil.amazon1 I/art﹕ Background sticky concurrent mark sweep GC freed 1464(89KB) AllocSpace objects, 7(2MB) LOS objects, 7% free, 9MB/9MB, paused 75.596ms total 203.616ms
03-07 00:59:25.338 2107-2413/com.example.nikhil.amazon1 E/SQLiteLog﹕ (1) no such table: products
03-07 00:59:25.339 2107-2413/com.example.nikhil.amazon1 E/SQLiteDatabase﹕ Error inserting price= 24,599.00 title=Google Nexus 5 D821 (16GB, Black) url=http://www.amazon.in/Google-Nexus-D821-16GB-Black/dp/B00GC1J55C/ref=sr_1_1?s=electronics&ie=UTF8&qid=1421161258&sr=1-1&keywords=Google
android.database.sqlite.SQLiteException: no such table: products (code 1): , while compiling: INSERT INTO products(price,title,url) VALUES (?,?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
at com.example.nikhil.amazon1.MySQLiteHelper.add(MySQLiteHelper.java:86)
at com.example.nikhil.amazon1.FirstParsing$1.run(FirstParsing.java:71)
at java.lang.Thread.run(Thread.java:818)
03-07 00:59:22.684 2107-2147/com.example.nikhil.amazon1 W/EGL_仿真﹕ 未实现eglSurfaceAttrib
03-07 00:59:22.684 2107-2147/com.example.nikhil.amazon1 W/opengl渲染器﹕ 未能在表面0xa5683060上设置EGL_交换_行为,错误=EGL_成功
03-07 00:59:24.922 2107-2120/com.example.nikhil.amazon1我/艺术﹕ 背景粘性并发标记扫描GC释放1464(89KB)AllocSpace对象,7(2MB)LOS对象,7%空闲,9MB/9MB,暂停75.596ms总计203.616ms
03-07 00:59:25.338 2107-2413/com.example.nikhil.amazon1 E/SQLiteLog﹕ (1) 没有这样的表:产品
03-07 00:59:25.339 2107-2413/com.example.nikhil.amazon1 E/SQLiteDatabase﹕ 插入price=24599.00 title=Google Nexus 5 D821(16GB,黑色)url时出错=http://www.amazon.in/Google-Nexus-D821-16GB-Black/dp/B00GC1J55C/ref=sr_1_1?s=electronics&ie=UTF8&qid=1421161258&sr=1-1&keywords=Google
android.database.sqlite.SQLiteException:没有这样的表:产品(代码1),编译时:插入到产品(价格、标题、url)值(?,,?)
位于android.database.sqlite.SQLiteConnection.nativePrepareStatement(本机方法)
位于android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
位于android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
位于android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
位于android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:58)
位于android.database.sqlite.SQLiteStatement.(SQLiteStatement.java:31)
位于android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
位于android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
位于com.example.nikhil.amazon1.MySQLiteHelper.add(MySQLiteHelper.java:86)
位于com.example.nikhil.amazon1.FirstParsing$1.run(FirstParsing.java:71)
运行(Thread.java:818)
我的问题完全类似于:
(一)
(二)
(三)
但是我发现很难理解它并将其应用到我的代码中。这可能有助于未来的开发 MySQLiteHelper-定义数据库、表等
public class MySQLiteHelper extends SQLiteOpenHelper {
private static final String FILE_NAME = "application.db";
private static final int DB_VERSION = 1;
private final String TAG = MySQLiteHelper.class.getCanonicalName();
private static SQLiteDatabase database = null;
public MySQLiteHelper(Context context) {
super(context, FILE_NAME, null, DB_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
//version 1
database.execSQL(ProductsTbl.CREATE_SQL);
//can create new tables if necessary, make sure to increase database version
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.i(TAG, "Upgrading from version " + oldVersion + " to version "
+ newVersion);
for (int i = oldVersion + 1; i <= newVersion; i++) {
Log.i(TAG, "version is becoming current " + i);
switch (i) {
case 2:
db.execSQL(ProductsTbl.CREATE_SQL);
break;
//add more cases for each additional table added
}
}
}
public static class ProductsTbl {
public static final String TABLE_NAME = "products";
public static final String ID = "_id";
public static final String URL = "url";
public static final String TITLE = "title";
public static final String PRICE = "price";
public static final String[] TABLE_COLUMNS = { ID, URL, TITLE, PRICE };
public static final String CREATE_SQL = "create table " + TABLE_NAME
+ "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ URL + " TEXT,"
+ TITLE + " TEXT,"
+ PRICE + " INTEGER);";
}
}
下面是如何在活动或类似活动中使用这两个类
public static void addProductToDB(String url, String title, String price) {
MySQLiteDatasource datasource = new MySQLiteDatasource(this);
datasource.open();
datasource.insertProduct(url, title, price);
datasource.close();
}
您可能还需要考虑定义一个产品对象来保存以后从数据库中获取的数据。您的代码中说的是
“CREATE TABLE TABLE\u NAME”(
)。它不应该说“CREATE TABLE”+TABLE\u NAME+”(“
?哦!实际上我有一个名为TABLE\u NAME的变量。为了避免复杂性,我没有把我的全部代码放在这里。是的,但您的代码创建的是一个名为“TABLE\u NAME”的表,而不是“products”,我想我没有解释,或者我不明白您的意思,对不起……我的意思是“创建TABLE\u NAME(”
正在创建一个名为table\u NAME的表。您的代码应该是“CREATE table”+table\u NAME+”(“
使用您的私有静态最终字符串table\u NAME=“products”;
我假设数据库文件仍然存在,并且当前的版本代码为1
,这意味着您的onUpgrade
方法将永远不会被调用,因为数据库已经是最新版本。删除数据库文件。您可以通过在设备上卸载应用程序或清除应用程序的存储来完成此操作。Y您还可以增加DB版本代码。但是,您更新的表创建代码现在有语法错误。您需要在字符串的末尾添加一个空格字符“CREATE table”
,否则生成的SQL代码如下所示:CREATE TABLEproducts…
。谢谢!我更改了它。但结果仍然相同。:)您是否尝试进入应用程序管理器并强制停止/清除数据/清除缓存并尝试重新打开应用程序?您是否也可以发布INSERT语句?我更新了我的add()方法。我在insert语句中得到一个错误,即称为products的表不存在。我将查看它。我认为您应该重新构造使用数据库的方式。我将发布一些更新的代码。
public static void addProductToDB(String url, String title, String price) {
MySQLiteDatasource datasource = new MySQLiteDatasource(this);
datasource.open();
datasource.insertProduct(url, title, price);
datasource.close();
}