好的,所以我在桌面上使用SQLite3创建了一个仅需读取某些信息的数据库。我正在制作的应用程序不需要在此表中插入或删除信息。
我已经在Room数据库层上进行了一些Google搜索,并且所有文档都要求在构建应用程序时在Room中创建一个新的数据库,这是我不想要的,因为我已经拥有一个数据库。
我应该如何让Room读取一个已经存在的数据库?我的数据库当前存储在/app/src/main/assets/splitbilldatabase.db
中。
答案 0 :(得分:2)
如果使用的是Room 2.2.0或更高版本,则可以将数据库构建器配置为从资产文件夹中加载数据库开始。
Room.databaseBuilder(appContext, AppDatabase.class, "splitbilldatabase.db")
.createFromAsset("splitbilldatabase.db")
.build()
更多信息: -https://developer.android.com/training/data-storage/room/prepopulate
答案 1 :(得分:1)
您需要做的第一件事是为要导入的Room模式创建所有内容(@Database,为表创建@Entity,等等),这必须完全匹配数据库的模式以被导入。
应该将外部数据库文件(如您所愿)复制到资产文件夹。
然后,您基本上可以先复制文件,然后再尝试打开Room数据库,例如RoomDatabase
init
方法中,但是仅当文件/数据库尚不存在时。
以下是一个有效(但未经广泛测试)的示例:-
@Database(entities = {MyTable.class,
MyOthertable.class,
MyMappingTable.class},version = 1,
exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {
public static final String DBNAME = "splitbilldatabase.db";
public static final String TB_MYTABLE = "mytable";
public static final String TB_MYOTHERTABLE = "myothertable";
public static final String TB_MYMAPPINGTABLE = "mymappingtable";
public static final String COL_MYTABLE_ID = BaseColumns._ID;
public static final String COL_MYTABLE_NAME = "_name";
public static final String COL_MYTABLE_DESCRIPTION = "_description";
public static final String COL_MYOTHERTABLE_ID = BaseColumns._ID;
public static final String COL_MYOTHERTABLE_OTHERDETAILS = "_otherdetails";
public static final String COL_MYMAPPINGTABLE_MYTABLEREFERENCE = "_mytable_reference";
public static final String COL_MYMAPPINGTABLE_MYOTEHERTABLEREFERENCE = "_myothertable_reference";
public abstract MyTableDao myTableDao();
public abstract MyOtherTableDao myOtherTableDao();
public abstract MyMappingTableDao myMappingTableDao();
public MyDatabase() {
super();
}
@Override
public void init(@NonNull DatabaseConfiguration configuration) {
importExistingDatabase(configuration.context, true); //<<<<<<<<<< Invokes the Import of the Exisiting Database.
super.init(configuration);
}
private void importExistingDatabase(Context context, boolean throw_exception) {
int buffer_size = 32768;
File dbpath = context.getDatabasePath(DBNAME);
if (dbpath.exists()) {
return; // Database already exists
}
// Just in case make the directories
File dirs = new File(dbpath.getParent());
dirs.mkdirs();
int stage = 0;
byte[] buffer = new byte[buffer_size];
long total_bytes_read = 0;
long total_bytes_written = 0;
int bytes_read = 0;
try {
InputStream assetdb = context.getAssets().open(DBNAME);
stage++;
dbpath.createNewFile();
stage++;
OutputStream realdb = new FileOutputStream(dbpath);
stage++;
while((bytes_read = assetdb.read(buffer)) > 0) {
total_bytes_read = total_bytes_read + bytes_read;
realdb.write(buffer,0,bytes_read);
total_bytes_written = total_bytes_written + bytes_read;
}
stage++;
realdb.flush();
stage++;
assetdb.close();
stage++;
realdb.close();
stage++;
} catch (IOException e) {
String failed_at = "";
switch (stage) {
case 0:
failed_at = "Opening Asset " + DBNAME;
break;
case 1:
failed_at = "Creating Output Database " + dbpath.getAbsolutePath();
break;
case 2:
failed_at = "Genreating Database OutputStream " + dbpath.getAbsolutePath();
break;
case 3:
failed_at = "Copying Data from Asset Database to Output Database. " +
" Bytes read=" + String.valueOf(total_bytes_read) +
" Bytes written=" + String.valueOf(total_bytes_written);
break;
case 4:
failed_at = "Flushing Written Data (" +
String.valueOf(total_bytes_written) +
" bytes written)";
break;
case 5:
failed_at = "Closing Asset Database File.";
break;
case 6:
failed_at = "Closing Created Database File.";
}
String msg = "An error was encountered copying the Database " +
"from the asset file to New Database. " +
"The error was encountered whilst :-\n\t" + failed_at;
Log.e("IMPORTDATABASE",msg);
e.printStackTrace();
if (throw_exception) {
throw new RuntimeException(msg);
}
}
}
}