0
votes

How to insert test data in room database before on application startup? I've tried to add callback in my viewmodel

AppDatabase appDatabase = Room.databaseBuilder(application, AppDatabase.class, "db")
                .fallbackToDestructiveMigration()
                .addCallback(new DatabaseCallback())
                .allowMainThreadQueries()
                .build();

The callback code is this:

@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
    super.onCreate(db);
}

@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
    super.onOpen(db);
    db.beginTransaction();
    db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Basketball","BOTH","TEAM"});
    db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Football","MALE","TEAM"});
    db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Ping Pong","BOTH","SINGLE"});
    db.endTransaction();
}

@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
    super.onDestructiveMigration(db);
}

the onCreate is never called(i don't know why).I thought this is because of backup,so i disabled it in manifest - but onCreate is still not called.If someone knows why,please tell me. Also onOpen is called after the first room method is called and not before.But even with this,after querying the data second time(after the onOpen has been called),data isn't still there.There is the Sport entity:

@Entity

public final class Sport {

@PrimaryKey(autoGenerate = true)
private long sportId;

private String sportName;

private Gender gender;

private SportType sportType;

public Sport(long sportId, String sportName, Gender gender, SportType sportType) {
    this.sportId = sportId;
    this.sportName = sportName;
    this.gender = gender;
    this.sportType = sportType;
}

public long getSportId() {
    return sportId;
}

public String getSportName() {
    return sportName;
}

public Gender getGender() {
    return gender;
}

public void setGender(Gender gender) {
    this.gender = gender;
}

public SportType getSportType() {
    return sportType;
}

public void setSportType(SportType sportType) {
    this.sportType = sportType;
}

}

Here is the DAO class(i call the loadAllSports,but empty list is returned):

@Dao

public interface SportDao {

@Query("SELECT * FROM Sport")
List<Sport> loadAllSports();

@Insert
void insertSport(Sport sport);

@Update
void updateSport(Sport sport);

@Delete
void deleteSport(Sport sport);

@Query("SELECT sportId,sportName FROM Sport")
LiveData<List<SportIdNameModel>> sportIdsAndNames();

}

And here is the database class:

@Database(entities = {Team.class, Athlete.class, Sport.class}, version = 3)

@TypeConverters({LocalDateConverter.class, GenderConverter.class, SportTypeConverter.class}) public abstract class AppDatabase extends RoomDatabase {

public abstract AthleteDao athleteDao();

public abstract TeamDao teamDao();

public abstract SportDao sportDao();

}

2

2 Answers

0
votes

In your database class

@Database(entities = {Team.class, Athlete.class, Sport.class}, version = 3)
@TypeConverters({LocalDateConverter.class, GenderConverter.class, SportTypeConverter.class}) 
public abstract class AppDatabase extends RoomDatabase {
    public abstract AthleteDao athleteDao();
    public abstract TeamDao teamDao();
    public abstract SportDao sportDao();

class CallBack extends RoomDatabase.Callback {
    @Override
    public void onCreate(@NonNull SupportSQLiteDatabase db) {
        super.onCreate(db);

        db.beginTransaction();
        db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Basketball","BOTH","TEAM"});
        db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Football","MALE","TEAM"});
        db.execSQL("INSERT INTO Sport('sportName','gender','sportType') VALUES(?,?,?)",new Object[]{"Ping Pong","BOTH","SINGLE"});
        db.endTransaction();
    }
}

then

AppDatabase appDatabase = Room.databaseBuilder(application, AppDatabase.class, "db")
                .fallbackToDestructiveMigration()
                .addCallback(new AppDatabase.CallBack())
                .allowMainThreadQueries()
                .build();

For adding data to your database for the first time, you need to override the onCreate method. For doing something every time you open the database, you have to override onOpen method.

-1
votes

Check this out: https://medium.com/androiddevelopers/7-pro-tips-for-room-fbadea4bfbd1#4785

Here is how it's done in the android sunflower demo: https://github.com/android/sunflower/blob/46c0db57a4a7bae070c66fd390b920de4c3cf27f/app/src/main/java/com/google/samples/apps/sunflower/data/AppDatabase.kt#L54

Edit: one of the biggest difference I can spot on first glance between your code and Google's is that you've put your seeding logic inside onOpen whereas they've put theirs in onCreate

Edit2: also they've moved their insert statements to the IO thread

Edit3: they've also used their daos, instead of execSql