通过提供的示例,我完全能够使用 Sugar ORM。
在我的用例中,我从服务器下载了一个 SQLite DB(它的 ETL 负载有数百万条记录,因此必须在服务器端完成)。下载保存到内部存储上的自定义路径。
就我而言,我不需要基于 POCO 的动态数据库创建。
如果所有 POCO 类字段与表结构匹配,是否可以将 Sugar ORM 与预先存在的 SQLite DB 一起使用,指向自定义路径?
首先,我对 Sugar 扩展 app 类的想法不满意。如果我在应用启动前还有其他任务需要执行怎么办?!因此,让我们用我们自己的 AppClass 扩展 SugarApp,然后在清单中注册 appClass 名称。此外,这是我第一次相信初始化 db 的正确位置。
public class MyAppStartClass extends SugarApp {
@Override
public final void onCreate() {
init();
super.onCreate();
}
private void init() {
initDB();
}
private void initDB() {
try {
if (!doesDatabaseExist(this, consts.dbPath)) {
Context context = getApplicationContext();
SQLiteDatabase db = context.openOrCreateDatabase(consts.dbName, context.MODE_PRIVATE, null);
db.close();
InputStream dbInput = getApplicationContext().getAssets().open(consts.dbName);
String outFileName = consts.dbPath;
OutputStream dbOutput = new FileOutputStream(outFileName);
try {
byte[] buffer = new byte[1024];
int length;
while ((length = dbInput.read(buffer)) > 0) {
dbOutput.write(buffer, 0, length);
}
} finally {
dbOutput.flush();
dbOutput.close();
dbInput.close();
}
}
} catch (Exception e) {
e.toString();
}
}
private boolean doesDatabaseExist(ContextWrapper context, String dbName) {
File dbFile = context.getDatabasePath(dbName);
return dbFile.exists();
}
}
清单:android:name="com.myPackageName.MyAppStartClass"
确保首先创建一个空数据库,否则会从 FileOutputStream() 和 dbPath = /data/data/com.myPackageName/databases/myDb.db 收到错误
SQLiteDatabase db = context.openOrCreateDatabase(consts.dbName, context.MODE_PRIVATE, null);
db.close();
确保您现有的数据库架构具有主键列 ID。哦耶!Sugar 仅将 ID 视为检索数据的主键。
如果您想使用现有表,请不要在扩展 SugarRecord 时指定 T 并且您必须将 Sugar 添加为模块并且您的项目依赖于它!
public class Book extends SugarRecord {
String title;
String edition;
public Book(){
}
public Book(String title, String edition){
this.title = title;
this.edition = edition;
}
}
6.如果你想使用现有的表。请注意,Sugar 会查找大写的列名,因此如果您现有的表列名是小写的,您将永远无法从中获取任何现有数据!
7.这让我不情愿地得出结论:如果您从头开始启动数据库并使用它为您生成数据库和表,Sugar 非常棒。但当您已经拥有一个包含数据的现有数据库时,情况并非如此。
我找到的解决方案是将您的 db 文件放在 assets 文件夹中。而不是读取 .csv 文件来创建 .db 文件(当您开始正确的活动时)首先尝试检查 .db 文件是否在 /data/data/file.db 中,如果不是,请从您的资产文件夹到该路径。使用下一个代码,您将能够完成所有操作:
protected void copyDataBase() throws IOException {
//Open your local db as the input stream
InputStream myInput = getApplicationContext().getAssets().open("file.db");
// Path to the just created empty db
String outFileName = "/data/data/com.yourpackagename/databases/" + "file.db";
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
protected boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = "/data/data/com.yourpackage/databases/" + "file.db";
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
我还没试过。但是,如果您可以将数据库文件复制到 /data/data//db_name.db 位置并在清单中的 Sugar 配置中使用相同的 db_name 和 db 版本,它应该会选择它。