Skip to content
Advertisement

Room Database Empty when Restarted App ( Same DB Name)

I am newbie to the Android X Room Database. Earlier I used Sqlitehelper class to access the sqlite databases and then migrated to 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. 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 . As I need to create the tablets in a single database i used same CONSTANTS.ITINERARY_TABLE for all of them. If I use differnt names in CONSTANTS.ITINERARY_TABLE this works fine. 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

Advertisement

Answer

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.

That is how you tell Room what tables will be created.

Where you use ItineraryDatabase.class, CONSTANTS.ITINERARY_TABLE, this is telling Room that the database (i.e. the file name) will be named as per 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).

  • you may wish to edit your question to say more about what you are trying to achieve and you may therefore get more elaborate and specific answers. If you do then feel free to notify myself by comment as such to this answer. At the minimum I would then look at any changes, but there is a very good chance that I would elaborate.

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) ? One Database Class with multiple getinstance?

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);-

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) :-

@Entity(tableName = CONSTANTS.ITINERARY_TABLE)
class ItineraryTable01 extends ItineraryData {
}

ItineraryTable02 (cheat again):-

@Entity(tableName = CONSTANTS.ITINERARY_TABLE_2)
class ItineraryTable02 extends ItineraryData {
}

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();
}
  • commented out LiveData so can run on MainThread (although queries not used in demo, but just in case)
  • note the close duplications for each table.

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;
      }
   }
}
  • allow to run on Main thread, otherwise unchanged (no need for callback though, it does nothing)

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:-

enter image description here

and

enter image description here

Run again (aka rerun)

enter image description here

and

enter image description here

  • as can be seen the data (rows highlighted) from the first run has been retained and data from the second run has been added (different generated id’s and timestamps)
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement