如何将现有的 SQLite3 数据库导入 Room?
How do I import an existing SQLite3 database into Room?
好的,所以我在桌面上使用 SQLite3 创建了一个只需要读取的某些信息的数据库。我正在制作的应用程序不需要在此 table.
中插入或删除信息
我已经在 Room 数据库层上进行了相当多的谷歌搜索,所有文档都需要在构建应用程序时在 Room 中创建一个新数据库——这是我不想要的,因为我已经有了一个。
我该如何让 Room 读取已经存在的数据库?我的数据库当前存储在 /app/src/main/assets/splitbilldatabase.db
.
您需要做的第一件事是为准备好导入的 Room 模式创建所有内容(@Database、@Entity 用于表等),这必须完全匹配要导入的数据库的架构。
应将外部数据库文件复制(如您所用)到资产文件夹。
然后您基本上可以在尝试打开 Room 数据库之前复制文件,例如在 RoomDatabase
init
方法中,但 仅当 file/database 不存在时 .
以下是一个有效(但未经过广泛测试)的示例:-
@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);
}
}
}
}
- 请注意假设文件名相同。
如果您使用的是 Room 2.2.0 或更高版本,您可以将数据库构建器配置为通过从资产文件夹加载数据库来启动。
Room.databaseBuilder(appContext, AppDatabase.class, "splitbilldatabase.db")
.createFromAsset("splitbilldatabase.db")
.build()
更多信息:
- https://developer.android.com/training/data-storage/room/prepopulate
好的,所以我在桌面上使用 SQLite3 创建了一个只需要读取的某些信息的数据库。我正在制作的应用程序不需要在此 table.
中插入或删除信息我已经在 Room 数据库层上进行了相当多的谷歌搜索,所有文档都需要在构建应用程序时在 Room 中创建一个新数据库——这是我不想要的,因为我已经有了一个。
我该如何让 Room 读取已经存在的数据库?我的数据库当前存储在 /app/src/main/assets/splitbilldatabase.db
.
您需要做的第一件事是为准备好导入的 Room 模式创建所有内容(@Database、@Entity 用于表等),这必须完全匹配要导入的数据库的架构。
应将外部数据库文件复制(如您所用)到资产文件夹。
然后您基本上可以在尝试打开 Room 数据库之前复制文件,例如在 RoomDatabase
init
方法中,但 仅当 file/database 不存在时 .
以下是一个有效(但未经过广泛测试)的示例:-
@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);
}
}
}
}
- 请注意假设文件名相同。
如果您使用的是 Room 2.2.0 或更高版本,您可以将数据库构建器配置为通过从资产文件夹加载数据库来启动。
Room.databaseBuilder(appContext, AppDatabase.class, "splitbilldatabase.db")
.createFromAsset("splitbilldatabase.db")
.build()
更多信息: - https://developer.android.com/training/data-storage/room/prepopulate