Cannot find enough resources to create a one-to-many relationship following MVVM architecture. So far this was the close a topic: Android Room: How works One to many relationship + examples
Have read: Android Room One-to-Many Relationship
Related but not the same, also the implementation of appdatabase is on MainActivity.class and not using async task.
Situation: I want to create a room database with the one-to-many relationships as the figure below: so that question choices can scale up on one to many choices.
Figure: database diagram
A table consisting of one assessments question, and selected_answer with many choices
Problem: Upon following the instruction in the thread above, I cannot figure out how can I pre-populate the database in the app database class.
Goal I want to achieve:
Pre-populate with insert statement assessments_with_choices table on app_database. Retrieve the live-data assessments list with choices in order to display the in UI. If possible reply with java, I do not know kotlin yet, sorry in advance. If possible please include a database inspector of the result. Or a dao insert query to insert new assessments, with a list of choices
Classes
Assessments.java
@Entitypublic class Assessments {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "uid_assessments")
private int uid_assessments;
@NonNull
@ColumnInfo(name = "question")
private String question;
@NonNull
@ColumnInfo(name = "selected")
private String selected;
public Assessments(@NonNull String question, @NonNull String selected) {
this.question = question;
this.selected = selected;
}
public int getUid_assessments() {
return uid_assessments;
}
public void setUid_assessments(int uid_assessments) {
this.uid_assessments = uid_assessments;
}
@NonNull
public String getQuestion() {
return question;
}
public void setQuestion(@NonNull String question) {
this.question = question;
}
@NonNull
public String getSelected() {
return selected;
}
public void setSelected(@NonNull String selected) {
this.selected = selected;
}
}
Choices.java
@Entity(foreignKeys = @ForeignKey(
entity = Assessments.class,
parentColumns = "uid_assessments",
childColumns = "fk_uid_assessments",
onDelete = ForeignKey.CASCADE
))
public class Choices {
@PrimaryKey(autoGenerate = true)
private int uid_choices;
@ColumnInfo(name = "fk_uid_assessments")
private int fk_uid_assessments;
@ColumnInfo(name = "choices")
private String choices;
public Choices(String choices) {
this.choices = choices;
}
public int getUid_choices() {
return uid_choices;
}
public void setUid_choices(int uid_choices) {
this.uid_choices = uid_choices;
}
public int getFk_uid_assessments() {
return fk_uid_assessments;
}
public void setFk_uid_assessments(int fk_uid_assessments) {
this.fk_uid_assessments = fk_uid_assessments;
}
public String getChoices() {
return choices;
}
public void setChoices(String choices) {
this.choices = choices;
}
}
AssessmentsWithChoices.java
public class AssessmentsWithChoices {
@Embedded
public Assessments assessments;
@Relation(parentColumn = "uid_assessments", entityColumn = "uid_choices")
public List<Choices> choices;
public AssessmentsWithChoices(Assessments assessments, List<Choices> choices){
this.assessments = assessments;
this.choices = choices;
}
}
AssessmentsDao.java
@Dao
public interface AssessmentsDao {
@Transaction
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertAssessments(Assessments assessments);
@Insert
void insertChoices(List<Choices> choices);
}
AssessmentsRepository.java
public class AssessmentsRepository {
private AssessmentsDao assessmentsDao;
public AssessmentsRepository(Application application) {
AppDatabase appDatabase = AppDatabase.getDbInstance(application);
this.assessmentsDao = assessmentsDao;
}
public void insert(AssessmentsWithChoices assessmentsWithChoices) {
new InsertAssessmenstAsyncTask(assessmentsDao).execute(assessmentsWithChoices);
}
public static class InsertAssessmenstAsyncTask extends AsyncTask<AssessmentsWithChoices, Void, Void> {
private AssessmentsDao assessmentsDao;
public InsertAssessmenstAsyncTask(AssessmentsDao assessmentsDao) {
this.assessmentsDao = assessmentsDao;
}
@Override
protected Void doInBackground(AssessmentsWithChoices... assessmentsWithChoices) {
int uid = (int) assessmentsDao.insertAssessments(assessmentsWithChoices[0].assessments);
for (Choices choices : assessmentsWithChoices[0].choices) {
choices.setFk_uid_assessments(uid);
}
assessmentsDao.insertChoices(assessmentsWithChoices[0].choices);
return null;
}
}
}
AssessmentsViewModel.java
public class AssessmentsViewModel extends AndroidViewModel {
private AssessmentsRepository assessmentsRepository;
public AssessmentsViewModel(@NonNull Application application) {
super(application);
assessmentsRepository = new AssessmentsRepository(application);
}
public void insertAssessmentsWithChoices(AssessmentsWithChoices assessmentsWithChoices){
assessmentsRepository.insert(assessmentsWithChoices);
}
}
AppDatabase.java
@Database(entities = {Assessments.class, Choices.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateAssessmentsWithChoicesAsyncTask(INSTANCE).execute();
}
};
public static synchronized AppDatabase getDbInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "DB_NAME")
.allowMainThreadQueries()
.addCallback(roomCallback)
.build();
}
return INSTANCE;
}
public abstract AssessmentsDao assessmentsDao();
//Problem: How can I pre-populate the one-many assessmentwithchoices on appDatabase
private static class PopulateAssessmentsWithChoicesAsyncTask extends AsyncTask<AssessmentsWithChoices, Void, Void> {
private AssessmentsDao assessmentsDao;
public PopulateAssessmentsWithChoicesAsyncTask(AppDatabase instance) {
assessmentsDao = instance.assessmentsDao();
}
@Override
protected Void doInBackground(AssessmentsWithChoices... assessmentsWithChoices) {
int uid = (int) assessmentsDao.insertAssessments(assessmentsWithChoices[0].assessments);
Log.d("TAG", "doInBackground: assessment" + uid);
for (Choices choices : assessmentsWithChoices[0].choices) {
choices.setFk_uid_assessments(uid);
}
assessmentsDao.insertChoices(assessmentsWithChoices[0].choices);
return null;
}
}
}
Sorry: I do not know how to syntax code highlight
**Goal I want to achieve: **
Pre-populate with insertstatement assessments_with_choices table on app_database. Retrieve the livedata assessments listwithchoices in order to display the in UI. If possible reply with java, I do not know kotlin yet, sorry in advance. If possible please include database inspector of result.