0

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.

  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Nov 11 '22 at 10:16

0 Answers0