这个问题在某种程度上与我的最后一个问题 https://stackoverflow.com/q/69384937/3692177,因为这是同一个项目,但现在我正努力向前迈进一步。
所以,在我之前的问题中,我只有一张桌子;这次我有两个表:新的第二个表应该包含第一个表的行的相关属性,处于 OneToMany 关系中。因此,我在第二个表中存储一个外键,该表将存储第一个表的相关行的行 ID(显然)。
问题是这样的:目的是使用相同的形式同时创建两个寄存器(父寄存器和子寄存器),并且 ParentTable 使用 AUTO_INCRMENT 作为其主键(又称为 ID)。
由于 RoomDb 的工作方式,我使用 POJO 进行创建:但插入后,据我所知,该 POJO 不会给我自动生成的 ID...所以,我能想象的唯一解决方法是,提交表单时,首先为父级进行 INSERT,然后使用创建父级的表单字段之一进行某种“SELECT * FROM Parent_table WHERE field1 LIKE :field1”,检索 ID,然后使用该 ID创建子表的POJO并执行下一个INSERT操作。然而,我觉得这种方法有些不对劲,上次我以这种方式实现类似的东西时,我最终得到了很多自定义侦听器和回调地狱(我仍然对此做噩梦)。
关于自定义侦听器的事情,它是我最终为不同项目的不同问题选择的解决方案(更多详细信息请参阅此老问题 https://stackoverflow.com/questions/52442384/how-can-i-make-some-class-running-in-the-main-thread-await-concurrently-for-ot/52493936#52493936)。看一下这个老问题可能有助于添加一些背景信息,说明我在 MVVM 架构中是多么被误导。但是,请注意当前的问题与 WebServices 无关,因为数据库纯粹位于手机应用程序的本地,没有外部来源。
然而,我想知道:这不是矫枉过正吗(我的意思是INSERT parent -> SELECT parentID -> INSERT child
事物)?这样做是不可避免的,还是有更干净的方法?
我的存储库类中的“创建方法”如下所示:
public void insertParent(Parent parent) {
new InsertParentAsyncTask(parent_dao).execute(parent);
}
private static class InsertParentAsyncTask extends AsyncTask<Parent, Void, Void> {
private final ParentDao parent_dao;
private InsertParentAsyncTask(ParentDao parent_dao) {
this.parent_dao = parent_dao;
}
@Override
protected Void doInBackground(Parent... parents) {
parent_dao.insert(parents[0]);
return null;
}
}
为了遵循 Mario 的答案,我在父母的 DAO 中更改了这个方法:
// OLD
@Insert
void insert(Parent parent);
// NEW (yes, I use short type for parent's ID)
@Insert
short insert(Parent parent);
EDIT2:现在,我尝试对存储库的插入 AsyncTask 进行更改,如下所示:
private static class InsertParentAsyncTask extends AsyncTask<Parent, Void, Short> {
private final ParentDao parent_dao;
private InsertParentAsyncTask(ParentDao parent_dao) {
this.parent_dao = parent_dao;
}
@Override
protected Short doInBackground(Parent... parents) {
short parent_id;
parent_id = parent_dao.insert(parents[0]);
return parent_id;
}
@Override
protected void onPostExecute(Short hanzi_id) {
// TODO ??? What now?
}
}
长话短说
它在这里对我有用,但这不是干净的代码(显然):
// TODO I am aware that AsyncTask is deprecated
// My Repository class uses this
public void insertParentAndChildren(Parent parent, String[] children_list) {
new InsertParentAndChildrenAsyncTask(parent_dao, children_list).execute(parent);
}
private static class InsertParentAndChildrenAsyncTask extends AsyncTask<Parent, Void, Short> {
private final ParentDao parent_dao;
private String[] children_list;
private InsertParentAndChildrenAsyncTask(ParentDao parent_dao, String[] children_list) {
this.parent_dao = parent_dao;
this.children_list = children_list;
}
@Override
protected Short doInBackground(Parent... parents) {
short parent_id;
Long row_id = parent_dao.insert(parents[0]);
parent_id = parent_dao.getIdForRowId(row_id);
return parent_id;
}
@Override
protected void onPostExecute(Short parent_id) {
// Second "create method" for children
for (int n = 0; n < children_list.length; n++) {
Child child = new Child();
child.setParentId( parent_id );
child.setMeaning( children_list[n] );
// My Repository has this method as well
insertChildStaticMethod(child);
}
}
}