[英]Room Database Empty when Restarted App ( Same DB Name)
I am newbie to the Android X Room Database.我是 Android X Room 数据库的新手。 Earlier I used Sqlitehelper class to access the sqlite databases and then migrated to room.
之前我用Sqlitehelper class访问sqlite的数据库,然后迁移到room。 The question is, when I insert data into Room database table it stores for that moment and when I restart the app the data is gone.
问题是,当我将数据插入 Room 数据库表时,它会在那一刻存储,而当我重新启动应用程序时,数据就会消失。 I want to have multiple tables in a single database.
我想在一个数据库中有多个表。
DAO:道:
@androidx.room.Dao
public interface ItineraryDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(ItineraryData model);
@Update
void update(ItineraryData model);
@Delete
void delete(ItineraryData model);
@Query("DELETE FROM "+ CONSTANTS.ITINERARY_TABLE)
void deleteAllItinerary();
@Query("SELECT * FROM "+CONSTANTS.ITINERARY_TABLE+" ORDER BY Date ASC")
LiveData<List<ItineraryData>> getAllItinerary();
Database:数据库:
@Database(entities = {ItineraryData.class},version = 1,exportSchema = false)
public abstract class ItineraryDatabase extends RoomDatabase {
private static ItineraryDatabase instance;
public abstract ItineraryDao Dao();
public static synchronized ItineraryDatabase getInstance(Context mCon){
if (instance == null) {
instance =
Room.databaseBuilder(mCon.getApplicationContext(),
ItineraryDatabase.class, CONSTANTS.ITINERARY_TABLE)
.fallbackToDestructiveMigration()
.addCallback(roomCallback)
.build();
}
return instance;
}
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
PopulateDbAsyncTask(ItineraryDatabase instance) {
ItineraryDao dao = instance.Dao();
}
@Override
protected Void doInBackground(Void... voids) {
return null;
}
The above is the code I used is every table to generate table with different Dao's.上面是我使用的代码是每个表用不同的 Dao 生成表。 As I need to create the tablets in a single database i used same CONSTANTS.ITINERARY_TABLE for all of them.
因为我需要在单个数据库中创建平板电脑,所以我对所有平板电脑都使用了相同的 CONSTANTS.ITINERARY_TABLE。 If I use differnt names in CONSTANTS.ITINERARY_TABLE this works fine.
如果我在 CONSTANTS.ITINERARY_TABLE 中使用不同的名称,则效果很好。 But it creates different databases.
但它会创建不同的数据库。
How can I create multiple tables in a single database without loosing data on restart.如何在单个数据库中创建多个表而不会在重新启动时丢失数据。 I went thorugh some earlier posts.
我浏览了一些较早的帖子。 But they suggest to use different database names.
但他们建议使用不同的数据库名称。
Thank you谢谢
How can I create multiple tables in a single database without loosing data on restart.
如何在单个数据库中创建多个表而不会在重新启动时丢失数据。
You define multiple tables by specifying multiple @Entity
annotated classes in the entities parameter of the @Database
annotation.您可以通过在
@Database
注释的entities 参数中指定多个@Entity
注释的类来定义多个表。
That is how you tell Room what tables will be created.这就是您告诉 Room 将创建哪些表的方式。
Where you use ItineraryDatabase.class, CONSTANTS.ITINERARY_TABLE
, this is telling Room that the database (ie the file name) will be named as per CONSTANTS.ITINERARY_TABLE
.在您使用
ItineraryDatabase.class, CONSTANTS.ITINERARY_TABLE
的地方,这告诉 Room 数据库(即文件名)将按照CONSTANTS.ITINERARY_TABLE
命名。
I suspect that you want the same table layout/schema but multiple tables (possibly itself not a good idea as each table has overheads when a single column could indicate the equivalent of the row belonging to a specific set of data).我怀疑您想要相同的表布局/架构但需要多个表(这本身可能不是一个好主意,因为当单个列可以指示属于特定数据集的行的等效项时,每个表都有开销)。
Additional (DEMO)附加(演示)
Considering the comment:-考虑评论:-
I want to have different table with different table schema's in a single database file.
我想在单个数据库文件中使用不同表模式的不同表。 I have seperate entity classes for them.
我为他们准备了单独的实体类。 Do i need to have getinstance for each table in this single class ( which extends with roomdatabase)?
我是否需要为这个单一的 class 中的每个表设置 getinstance(随 roomdatabase 扩展)? One Database Class with multiple getinstance?
具有多个 getinstance 的一个数据库 Class?
and also the presumption of a single schema (not that it matters much if not, simpler if not).以及单一模式的假设(并不是说如果没有就很重要,如果没有就更简单)。 Then consider the following code that is based very much on your code.
然后考虑以下非常基于您的代码的代码。
ItineraryData (used as a model for two tables, so not @Entity annotated - can be ignored if different schemas);- ItineraryData (用作两个表的 model,因此没有 @Entity 注释 - 如果模式不同,可以忽略);-
class ItineraryData {
@PrimaryKey
Long id=null;
long date=System.currentTimeMillis() / 1000;
@NonNull
String otherColumn;
}
CONSTANTS :-常量:-
class CONSTANTS {
static final String ITINERARY_TABLE = "it01";
static final String ITINERARY_TABLE_2 = "it02";
}
ItineraryTable01 (bit of a cheat as schema grabbed from ItineraryData):- ItineraryTable01 (从 ItineraryData 抓取的模式有点作弊):-
@Entity(tableName = CONSTANTS.ITINERARY_TABLE)
class ItineraryTable01 extends ItineraryData {
}
ItineraryTable02 (cheat again):- ItineraryTable02 (再次作弊):-
@Entity(tableName = CONSTANTS.ITINERARY_TABLE_2)
class ItineraryTable02 extends ItineraryData {
}
ItineraryDao ItineraryDao
@Dao
public interface ItineraryDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(ItineraryTable01 model);
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(ItineraryTable02 model);
@Update
void update(ItineraryTable01 model);
@Update
void update(ItineraryTable02 model);
@Delete
void delete(ItineraryTable01 model);
@Delete
void delete(ItineraryTable02 model);
@Query("DELETE FROM " + CONSTANTS.ITINERARY_TABLE)
void deleteAllItineraryTable01();
@Query("DELETE FROM " + CONSTANTS.ITINERARY_TABLE_2)
void deleteAllItineraryTable02();
@Query("SELECT * FROM " + CONSTANTS.ITINERARY_TABLE + " ORDER BY Date ASC")
/*LiveData<*/List<ItineraryTable01>/*>*/ getAllItineraryTable01();
@Query("SELECT * FROM " + CONSTANTS.ITINERARY_TABLE + " ORDER BY Date ASC")
/*LiveData<*/List<ItineraryTable02>/*>*/ getAllItineraryTable02();
}
ItineraryDatabase行程数据库
@Database(entities = { ItineraryTable01.class,ItineraryTable02.class/*ItineraryData.class*/} ,version = 1,exportSchema = false)
public abstract class ItineraryDatabase extends RoomDatabase {
private static ItineraryDatabase instance;
public abstract ItineraryDao Dao();
public static synchronized ItineraryDatabase getInstance(Context mCon) {
if (instance == null) {
instance =
Room.databaseBuilder(mCon.getApplicationContext(),
ItineraryDatabase.class, CONSTANTS.ITINERARY_TABLE)
.allowMainThreadQueries() /*<<<<<<<<<< Added for convenience brevity of demo */
.fallbackToDestructiveMigration()
.addCallback(roomCallback)
.build();
}
return instance;
}
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
PopulateDbAsyncTask(ItineraryDatabase instance) {
ItineraryDao dao = instance.Dao();
}
@Override
protected Void doInBackground(Void... voids) {
return null;
}
}
}
Finally to demo some code in an activity:-最后在活动中演示一些代码:-
public class MainActivity extends AppCompatActivity {
ItineraryDatabase db;
ItineraryDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ItineraryTable01 it01 = new ItineraryTable01();
ItineraryTable02 it02 = new ItineraryTable02();
it01.otherColumn = "blah01";
it02.otherColumn = "blah02";
db = ItineraryDatabase.getInstance(this);
dao = db.Dao();
/* Not until following code is executed is the database actually opened */
dao.insert(it01); /* Inserts into table01 */
dao.insert(it02); /* Inserts into table02 */
}
}
Results结果
When first run第一次运行时
Using App Inspection:-使用应用检查:-
and和
Run again (aka rerun)再次运行(又名重新运行)
and和
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.