我使用图书馆android-sqlite-asset-helper
需要更新,但是让用户保存了数据。表、列的名称保持不变。只有表中的条目数增加了。
我增加了 DATABASE_VERSION。将数据库放入存档中。如说明中所述,创建文件 - brodsky.db_upgrade_1-2.sql
ALTER TABLE "poems_table" RENAME TO 'poems_table_TMP'; CREATE TABLE
"poems_table" ( "id" long NOT NULL, "title" text, "poem" text,
"subject" text, "years" text, "favorite" text, PRIMARY KEY ("id") );
INSERT INTO "poems_table" ("id", "title", "poem", "subject",
"years", "favorite") SELECT "id", "title", "poem", "subject",
"years", "favorite" FROM "poems_table_TMP"; DROP TABLE
"poems_table_TMP";
数据库助手
public class PoemsDbHelper extends SQLiteAssetHelper {
private static String DB_NAME = "brodsky.db";
private static final int DB_VERSION = 2;
public PoemsDbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
}
没有任何改变。显示旧数据
最佳答案
根据您的代码,假设代码在 onUpgrade 方法中并且版本从 1 更改为 2,则代码没有任何用处。就是这样:-
- 重命名旧数据库的 poems_table
- 创建一个新的 poems_table
- 将重命名表的内容复制到新创建的表中
- 删除重命名的 poems_table。
它无处访问较新版本的 brodsky.db
您需要(我相信)做的是打开较新的 brodsky.db 并从该数据库复制数据。
工作示例
以下是此类工作示例的代码。
这将在数据库版本增加时(为简单起见任何升级):-
- 将新更新的数据库复制为一个单独的/附加的数据库,并
- 尝试将更新数据库中的行复制到现有数据库中
- 仅当它们不是现有行时(基于除 id 列之外的所有列,因为最终用户可能添加了诗歌并因此使用了 id)。
核心代码在 PoemsDbHelper.java 中并且是:-
public class PoemsDbHelper extends SQLiteAssetHelper {
public static final String DBNAME = "brodsky.db";
public static final int DBVERSION = 1;
public static final String TBLNAME = "poems_table";
public static final String COL_ID = "id";
public static final String COL_TITLE = "title";
public static final String COl_POEM = "poem";
public static final String COL_SUBJECT = "subject";
public static final String COL_YEARS = "years";
public static final String COL_FAVOURITE = "favorite";
Context mContext;
public PoemsDbHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mContext = context;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
getNewPoems(mContext, db); //<<<<<<<<<< get the new poems when upgraded
}
private void getNewPoems(Context context, SQLiteDatabase db) {
Log.d("GETNEWPOEMS","Initiating getting new poems due to Database version increased.");
// Prepare to copy the updated database from the assets folder
InputStream is;
OutputStream os;
final String tempnewdbname = "tempbrodsky.db";
int buffersize = 4096;
byte[] buffer = new byte[buffersize];
String newDBPath = mContext.getDatabasePath(tempnewdbname).getPath();
// If a copied version of the updated database exists then delete it
// This should not be required but better safe than sorry
File newDBFile = new File(newDBPath);
if (newDBFile.exists()) {
newDBFile.delete();
}
// Just in case create the databases directory (it should exist)
File newDBFileDirectory = newDBFile.getParentFile();
if (!newDBFileDirectory.exists()) {
newDBFileDirectory.mkdirs();
}
// Preapre to copy update database from the assets folder
try {
is = context.getAssets().open("databases/" + DBNAME);
os = new FileOutputStream(newDBFile);
int bytes_read;
while ((bytes_read = is.read(buffer,0,buffersize)) > 0) {
os.write(buffer);
}
os.flush();
os.close();
is.close();
}catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Ouch updated database not copied - processing stopped - see stack-trace above.");
}
long id = maxid(db) + 1; // Get the next available id
SQLiteDatabase newdb = SQLiteDatabase.openDatabase(newDBFile.getPath(),null,SQLiteDatabase.OPEN_READONLY);
Cursor csr = newdb.query(TBLNAME,null,null,null,null,null,null);
long insert_result;
db.beginTransaction();
while (csr.moveToNext()) {
insert_result = insertCorePoem(
db,
id,
csr.getString(csr.getColumnIndex(COL_TITLE)),
csr.getString(csr.getColumnIndex(COl_POEM)),
csr.getString(csr.getColumnIndex(COL_SUBJECT)),
csr.getString(csr.getColumnIndex(COL_YEARS)),
csr.getString(csr.getColumnIndex(COL_FAVOURITE))
);
// If the row was inserted then increment the if ready for the next insert
// If not inserted (result = -2) then leave id as it is as it was unused
if (insert_result > 0) {
id++;
}
}
db.setTransactionSuccessful();
db.endTransaction();
csr.close();
newDBFile.delete(); // Delete the copied database as no longer required
}
public long insertCorePoem(SQLiteDatabase db, long id, String title, String poem, String subject, String years, String favourite) {
String whereclause = COL_TITLE + "=? AND " + COl_POEM + "=? AND " + COL_SUBJECT + "=? AND " + COL_YEARS + "=?";
String[] whereargs = new String[]{
title,
poem,
subject,
years
};
Cursor csr = db.query(TBLNAME,null,whereclause,whereargs,null,null,null);
boolean rowexists = (csr.getCount() > 0);
csr.close();
if (rowexists) {
Log.d("INSERTCOREPOEM","Skipping insert of row");
return -2; // Don't insert if the poem already exists
}
ContentValues cv = new ContentValues();
cv.put(COL_ID,id);
cv.put(COL_TITLE,title);
cv.put(COl_POEM,poem);
cv.put(COL_SUBJECT,subject);
cv.put(COL_YEARS,years);
cv.put(COL_FAVOURITE,favourite);
Log.d("INSERTCOREPOEM","Inserting new column with id " + String.valueOf(id));
return db.insert(TBLNAME, null, cv);
}
private long maxid(SQLiteDatabase db) {
long rv = 0;
String extractcolumn = "maxid";
String[] col = new String[]{"max(" + COL_ID + ") AS " + extractcolumn};
Cursor csr = db.query(TBLNAME,col,null,null,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getLong(csr.getColumnIndex(extractcolumn));
}
csr.close();
return rv;
}
public Cursor getAllPoems() {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(TBLNAME,null,null,null,null,null,null);
}
}
- getNewPoems 是执行上述操作的主要方法(请注意它是如何从 onUpgrade 方法中调用的)。这从 assets 文件夹复制更新的数据库,然后提取所有诗歌(应用程序 () 提供的核心诗歌)。
- 准备插入列使用 maxid 方法从现有数据库获取当前最高 ID 并加 1,以便新的第一个 ID 是唯一的。
- 尝试插入每一行,但是如果要插入的行已经存在,那么它将被跳过。这是在 insertCorePoem 方法中确定的。
- getAllPoems 方法返回一个游标(由调用 Activity 使用)。
- 注意您可能有其他应包含的现有方法。
测试
使用外部工具创建了一个名为 brodsky.db 的数据库,其中包含 3 首诗。这被复制到 Assets 文件夹的数据库文件夹中。
调用 Activity 中使用了以下内容:-
public class MainActivity extends AppCompatActivity {
PoemsDbHelper mDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new PoemsDbHelper(this);
Log.d("DBVERSION", "Database version = " + String.valueOf(PoemsDbHelper.DBVERSION));
Cursor csr = mDBHlpr.getAllPoems();
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
阶段 1 - 验证/检查现有数据库
当第一次运行时,数据库(包含 3 首诗)从 assets 文件夹中复制并且日志包含(就像在这个阶段运行应用程序时一样):-
12-18 06:19:58.505 3574-3574/? D/DBVERSION: Database version = 1
12-18 06:19:58.505 3574-3574/? W/SQLiteAssetHelper: copying database from assets...
12-18 06:19:58.505 3574-3574/? W/SQLiteAssetHelper: database copy complete
12-18 06:19:58.521 3574-3574/? I/SQLiteAssetHelper: successfully opened database brodsky.db
12-18 06:19:58.521 3574-3574/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@534758c8
12-18 06:19:58.521 3574-3574/? I/System.out: 0 {
12-18 06:19:58.521 3574-3574/? I/System.out: id=1
12-18 06:19:58.521 3574-3574/? I/System.out: title=A Poem
12-18 06:19:58.521 3574-3574/? I/System.out: poem=This is a poem
12-18 06:19:58.521 3574-3574/? I/System.out: subject=poem
12-18 06:19:58.521 3574-3574/? I/System.out: years=2018
12-18 06:19:58.521 3574-3574/? I/System.out: favorite=NO
12-18 06:19:58.521 3574-3574/? I/System.out: }
12-18 06:19:58.521 3574-3574/? I/System.out: 1 {
12-18 06:19:58.521 3574-3574/? I/System.out: id=2
12-18 06:19:58.521 3574-3574/? I/System.out: title=Another Poem
12-18 06:19:58.521 3574-3574/? I/System.out: poem=This is another poem
12-18 06:19:58.521 3574-3574/? I/System.out: subject=another poem
12-18 06:19:58.521 3574-3574/? I/System.out: years=2017
12-18 06:19:58.521 3574-3574/? I/System.out: favorite=NO
12-18 06:19:58.521 3574-3574/? I/System.out: }
12-18 06:19:58.521 3574-3574/? I/System.out: 2 {
12-18 06:19:58.521 3574-3574/? I/System.out: id=3
12-18 06:19:58.521 3574-3574/? I/System.out: title=the Third Poem
12-18 06:19:58.521 3574-3574/? I/System.out: poem=This is the third poem
12-18 06:19:58.521 3574-3574/? I/System.out: subject=third poem
12-18 06:19:58.521 3574-3574/? I/System.out: years=2018
12-18 06:19:58.521 3574-3574/? I/System.out: favorite=NO
12-18 06:19:58.521 3574-3574/? I/System.out: }
12-18 06:19:58.521 3574-3574/? I/System.out: <<<<<
第 2 阶段 - 使用更新的数据库(但版本号未更改)。
- 使用 SQlite 工具将另外 3 行添加到数据库
- Assets 文件夹中的现有数据库已重命名(易于恢复以进行测试调试)。
- 更新的数据库已复制到 Assets 文件夹中的数据库文件夹中。
导致:-
然后重新运行该应用程序,但作为中间检查,版本号没有更改。结果高于预期,即由于版本号未更改,因此未运行 onUpgrade 方法。
第 3 阶段 - 更改版本号。
版本号从1增加到2,App运行。
导致按照 :- 添加 3 行
12-18 06:24:46.973 3689-3689/? D/DBVERSION: Database version = 2
12-18 06:24:46.981 3689-3689/? I/SQLiteAssetHelper: successfully opened database brodsky.db
12-18 06:24:46.981 3689-3689/? D/GETNEWPOEMS: Initiating getting new poems due to Database version increased.
12-18 06:24:46.981 3689-3689/? D/INSERTCOREPOEM: Skipping insert of row
12-18 06:24:46.985 3689-3689/? D/INSERTCOREPOEM: Skipping insert of row
12-18 06:24:46.985 3689-3689/? D/INSERTCOREPOEM: Skipping insert of row
12-18 06:24:46.985 3689-3689/? D/INSERTCOREPOEM: Inserting new column with id 4
12-18 06:24:46.985 3689-3689/? D/INSERTCOREPOEM: Inserting new column with id 5
12-18 06:24:46.985 3689-3689/? D/INSERTCOREPOEM: Inserting new column with id 6
12-18 06:24:46.993 3689-3689/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@53462060
12-18 06:24:46.993 3689-3689/? I/System.out: 0 {
12-18 06:24:46.993 3689-3689/? I/System.out: id=1
12-18 06:24:46.993 3689-3689/? I/System.out: title=A Poem
12-18 06:24:46.993 3689-3689/? I/System.out: poem=This is a poem
12-18 06:24:46.993 3689-3689/? I/System.out: subject=poem
12-18 06:24:46.993 3689-3689/? I/System.out: years=2018
12-18 06:24:46.993 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.993 3689-3689/? I/System.out: }
12-18 06:24:46.993 3689-3689/? I/System.out: 1 {
12-18 06:24:46.993 3689-3689/? I/System.out: id=2
12-18 06:24:46.993 3689-3689/? I/System.out: title=Another Poem
12-18 06:24:46.993 3689-3689/? I/System.out: poem=This is another poem
12-18 06:24:46.993 3689-3689/? I/System.out: subject=another poem
12-18 06:24:46.993 3689-3689/? I/System.out: years=2017
12-18 06:24:46.993 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.993 3689-3689/? I/System.out: }
12-18 06:24:46.993 3689-3689/? I/System.out: 2 {
12-18 06:24:46.993 3689-3689/? I/System.out: id=3
12-18 06:24:46.993 3689-3689/? I/System.out: title=the Third Poem
12-18 06:24:46.993 3689-3689/? I/System.out: poem=This is the third poem
12-18 06:24:46.993 3689-3689/? I/System.out: subject=third poem
12-18 06:24:46.993 3689-3689/? I/System.out: years=2018
12-18 06:24:46.993 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.993 3689-3689/? I/System.out: }
12-18 06:24:46.993 3689-3689/? I/System.out: 3 {
12-18 06:24:46.993 3689-3689/? I/System.out: id=4
12-18 06:24:46.993 3689-3689/? I/System.out: title=The Update Poem
12-18 06:24:46.993 3689-3689/? I/System.out: poem=This is a new poem
12-18 06:24:46.993 3689-3689/? I/System.out: subject=4th Core Poem
12-18 06:24:46.993 3689-3689/? I/System.out: years=2019
12-18 06:24:46.993 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.993 3689-3689/? I/System.out: }
12-18 06:24:46.993 3689-3689/? I/System.out: 4 {
12-18 06:24:46.993 3689-3689/? I/System.out: id=5
12-18 06:24:46.993 3689-3689/? I/System.out: title=Another Updated Poem
12-18 06:24:46.993 3689-3689/? I/System.out: poem=This is another updated poem
12-18 06:24:46.997 3689-3689/? I/System.out: subject=5th Core Poem
12-18 06:24:46.997 3689-3689/? I/System.out: years=2019
12-18 06:24:46.997 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.997 3689-3689/? I/System.out: }
12-18 06:24:46.997 3689-3689/? I/System.out: 5 {
12-18 06:24:46.997 3689-3689/? I/System.out: id=6
12-18 06:24:46.997 3689-3689/? I/System.out: title=The 3rd Updated Poem
12-18 06:24:46.997 3689-3689/? I/System.out: poem=This is the 3rd updated poem
12-18 06:24:46.997 3689-3689/? I/System.out: subject=6th Core Poem
12-18 06:24:46.997 3689-3689/? I/System.out: years=2019
12-18 06:24:46.997 3689-3689/? I/System.out: favorite=NO
12-18 06:24:46.997 3689-3689/? I/System.out: }
12-18 06:24:46.997 3689-3689/? I/System.out: <<<<<
再次运行应用程序,没有任何改变。
将版本增加到 3 会产生相同的 6 行。但是,onUpgrade 运行并尝试添加行但它们都被跳过,按照:-
12-18 06:27:08.933 3789-3789/so53801149.so53801149poemupdatefromassets D/DBVERSION: Database version = 3
12-18 06:27:08.937 3789-3789/so53801149.so53801149poemupdatefromassets I/SQLiteAssetHelper: successfully opened database brodsky.db
12-18 06:27:08.937 3789-3789/so53801149.so53801149poemupdatefromassets D/GETNEWPOEMS: Initiating getting new poems due to Database version increased.
12-18 06:27:08.937 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.945 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.945 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.945 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.945 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.945 3789-3789/so53801149.so53801149poemupdatefromassets D/INSERTCOREPOEM: Skipping insert of row
12-18 06:27:08.949 3789-3789/so53801149.so53801149poemupdatefromassets I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@5347529c
..... results same as above (6 rows)
- 注意您可能需要在 insertCorePoem 方法中定制查询以满足您的需要。
关于android - 更新数据库。 Sqlite-asset-helper 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53801149/