android - 如何在android房间加入查询中的内表中进行过滤
问题描述
我有两个表 A 表和 B 表,我在 android 房间进行内连接查询(A 内连接 B),但我必须从表 B 中过滤数据,这在 android 房间中可能吗?
解决方案
是的,但是您必须了解 Room 的工作原理以及 JOIN 的工作原理(即笛卡尔积,每个与过滤器匹配的组合都会有一行)
通常,您会使用带有TableA Embedded
( @Embedded
)的 POJO 和TableB作为@Relation
组合。例如:-
class TableAWithTableB {
@Embedded
TableA tableA;
@Relation(entity = TableB.class,parentColumn = "tableAId", entityColumn = "tableAMapId")
List<TableB> tableBList;
}
但是,Room 处理的方式@Relation
是它只从结果中检索父级,然后继续获取父级的所有子级。也就是说,如果过滤器在孩子身上,它会构建一个忽略过滤器的完整对象。
如果您希望将过滤器应用于孩子,那么您不会使用@Relation
但可以@Embedded
同时使用父母和孩子,但是您可以获得每个孩子的父母,因此可以有多个相同的父母。例如
class TableAJoinedWithTableB {
@Embedded
TableA tableA;
@Embedded
TableB tableB;
}
例子
考虑到这两个实体是:-
@Entity
class TableA {
@PrimaryKey
Long tableAId;
String nameA;
public TableA(){}
@Ignore
public TableA(String name){
this.nameA = name;
}
public Long getTableAId() {
return tableAId;
}
public void setTableAId(Long tableAId) {
this.tableAId = tableAId;
}
public String getName() {
return nameA;
}
public void setName(String name) {
this.nameA = name;
}
}
和:-
@Entity(
foreignKeys = {
@ForeignKey(
entity = TableA.class,
parentColumns = "tableAId",
childColumns = "tableAMapId"
)
}
)
class TableB {
@PrimaryKey
Long tableBId;
@ColumnInfo(index = true)
Long tableAMapId;
String nameB;
public TableB(){}
@Ignore
public TableB(long tableAMapId,String name) {
this.tableAMapId = tableAMapId;
this.nameB = name;
}
public Long getTableBId() {
return tableBId;
}
public void setTableBId(Long tableBId) {
this.tableBId = tableBId;
}
public Long getTableAMapId() {
return tableAMapId;
}
public void setTableAMapId(Long tableAMapId) {
this.tableAMapId = tableAMapId;
}
public String getName() {
return nameB;
}
public void setName(String name) {
this.nameB = name;
}
}
@Dao, AllDao是:-
@Dao
interface AllDao {
@Insert long insert(TableA tableA);
@Insert long[] insert(TableA...one_or_more_tableAs);
@Insert long insert(TableB tableB);
@Insert long[] insert(TableB...one_or_moretableBs);
@Query("DELETE FROM tableA") int deleteAllFROMTableA();
@Query("DELETE FROM tableB") int deleteAllFromTableB();
@Query("SELECT * FROM tablea") List<TableA> getALlFromTableA();
@Query("SELECT * FROM tableb") List<TableB> getAllFromTableB();
@Transaction @Query("SELECT tableA.* FROM tablea JOIN tableb ON tableAId = tableAMapId WHERE tableb.nameB >:arg")
List<TableAWithTableB> getSelectedViaRelation(String arg);
@Query("SELECT * FROM tablea JOIN tableb ON tableAId = tableAMapId WHERE tableb.nameB >:arg")
List<TableAJoinedWithTableB> getSelectedViaEmbedded(String arg);
}
@Database 类是TheDatabase(一个非常标准的),然后使用:-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
AllDao dao;
private static final String TAG = "TABLEINFO";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getDao();
dao.deleteAllFromTableB();
dao.deleteAllFROMTableA();
long row1Id = dao.insert(new TableA("ROW1"));
long row2Id = dao.insert(new TableA("ROW2"));
long row3Id = dao.insert(new TableA("ROW3"));
long row4Id = dao.insert(new TableA("ROW4"));
dao.insert(new TableB(row1Id,"A"));
dao.insert(new TableB(row1Id,"Z"));
dao.insert(new TableB(row1Id,"P"));
dao.insert(new TableB(row2Id,"B"));
dao.insert(new TableB(row2Id,"Y"));
dao.insert(new TableB(row2Id,"O"));
dao.insert(new TableB(row3Id,"C"));
dao.insert(new TableB(row3Id,"X"));
dao.insert(new TableB(row3Id,"N"));
dao.insert(new TableB(row4Id,"AA"));
dao.insert(new TableB(row4Id,"BB"));
for(TableAWithTableB t: dao.getSelectedViaRelation("M")) {
logTableA(t.tableA);
for(TableB tb: t.tableBList) {
logTableB(tb);
}
}
for (TableAJoinedWithTableB t: dao.getSelectedViaEmbedded("M")) {
Log.d(TAG,"TableA is " + t.tableA.getName() + " TableB is " + t.tableB.getName() + " Parent(TableA) ID is " + t.tableB.getTableAMapId());
}
}
private void logTableA(TableA tableA) {
Log.d(TAG,"TableA Name = " + tableA.getName());
}
private void logTableB(TableB tableB) {
Log.d(TAG,"\tTableB = " + tableB.getName() + " Parent TableA is " + tableB.getTableAMapId());
}
}
结果是 :-
2021-06-29 07:43:49.134 D/TABLEINFO: TableA Name = ROW1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = A Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = Z Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = P Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableA Name = ROW1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = A Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = Z Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = P Parent TableA is 1
2021-06-29 07:43:49.134 D/TABLEINFO: TableA Name = ROW2
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = B Parent TableA is 2
2021-06-29 07:43:49.134 D/TABLEINFO: TableB = Y Parent TableA is 2
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = O Parent TableA is 2
2021-06-29 07:43:49.135 D/TABLEINFO: TableA Name = ROW2
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = B Parent TableA is 2
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = Y Parent TableA is 2
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = O Parent TableA is 2
2021-06-29 07:43:49.135 D/TABLEINFO: TableA Name = ROW3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = C Parent TableA is 3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = X Parent TableA is 3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = N Parent TableA is 3
2021-06-29 07:43:49.135 D/TABLEINFO: TableA Name = ROW3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = C Parent TableA is 3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = X Parent TableA is 3
2021-06-29 07:43:49.135 D/TABLEINFO: TableB = N Parent TableA is 3
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW1 TableB is Z Parent(TableA) ID is 1
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW1 TableB is P Parent(TableA) ID is 1
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW2 TableB is Y Parent(TableA) ID is 2
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW2 TableB is O Parent(TableA) ID is 2
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW3 TableB is X Parent(TableA) ID is 3
2021-06-29 07:43:49.140 D/TABLEINFO: TableA is ROW3 TableB is N Parent(TableA) ID is 3
所以ROW4不存在,由于过滤,在任何一种方法中,但是:-
对于@Relation
TableB,结果是完整的 Table A 对象,忽略了关于子项的 WHERE 子句。
当@Embedded
用于 TableB 时,将应用过滤器,但您会为父级获得多行(就像没有空间一样)。
额外的
如果您想获得部分构建的 TableA 对象,即具有选择性子对象,那么您必须完成基础工作(就像使用原生 SQLite 一样)。您可以通过将相同的 TableA 合并到任何一个 POJO 类中来基于getSelectedViaEmbedded的结果构建它们(如果不是由房间构建的注释将被忽略)。例如考虑: -
class TableAsWithSelectiveTableB {
private ArrayList<TableAWithTableB> tableAWithTableBList = new ArrayList<>();
private TableAsWithSelectiveTableB(List<TableAJoinedWithTableB> baselist) {
String previousTableAName = "";
TableA currentTableA = null;
ArrayList<TableB> currentTableBList = new ArrayList<>();
boolean toBeApplied = false;
for (TableAJoinedWithTableB tabj: baselist) {
if (!tabj.tableA.nameA.equals(previousTableAName)) {
if (toBeApplied) {
TableAWithTableB apply = new TableAWithTableB();
apply.tableA = currentTableA;
apply.tableBList = currentTableBList;
tableAWithTableBList.add(apply);
}
toBeApplied = true;
currentTableA = tabj.tableA;
currentTableBList = new ArrayList<>();
previousTableAName = currentTableA.nameA;
}
currentTableBList.add(tabj.tableB);
}
if (toBeApplied) {
TableAWithTableB apply = new TableAWithTableB();
apply.tableA = currentTableA;
apply.tableBList = currentTableBList;
tableAWithTableBList.add(apply);
}
}
public static List<TableAWithTableB> getTableAWithTableBList(List<TableAJoinedWithTableB> list) {
return new TableAsWithSelectiveTableB(list).tableAWithTableBList;
}
}
用于:-
for(TableAWithTableB tatab: TableAsWithSelectiveTableB.getTableAWithTableBList(dao.getSelectedViaEmbedded("M"))) {
logTableA(tatab.tableA);
for(TableB tb: tatab.tableBList) {
Log.d(TAG,"\tTableB is " + tb.getName() + " Parent(TableA) ID is " + tb.getTableAMapId());
}
}
结果是:-
2021-06-29 10:00:41.432 D/TABLEINFO: TableA Name = ROW1
2021-06-29 10:00:41.432 D/TABLEINFO: TableB is Z Parent(TableA) ID is 1
2021-06-29 10:00:41.432 D/TABLEINFO: TableB is P Parent(TableA) ID is 1
2021-06-29 10:00:41.432 D/TABLEINFO: TableA Name = ROW2
2021-06-29 10:00:41.432 D/TABLEINFO: TableB is Y Parent(TableA) ID is 2
2021-06-29 10:00:41.433 D/TABLEINFO: TableB is O Parent(TableA) ID is 2
2021-06-29 10:00:41.433 D/TABLEINFO: TableA Name = ROW3
2021-06-29 10:00:41.433 D/TABLEINFO: TableB is X Parent(TableA) ID is 3
2021-06-29 10:00:41.433 D/TABLEINFO: TableB is N Parent(TableA) ID is 3
推荐阅读
- c# - 如何在bot框架的sql server中保存文件附件
- angular - 如果我们在单个模块中提及所有组件,这会影响代码或处理时间吗?
- solr - Solr在嵌套的n个级别和分面中显示文档
- javascript - 未捕获的类型错误:playlist.querySelector 不是函数
- wordpress - Wordpress 登录第一次需要很多时间。我该如何解决?
- java - Firebase 数据库数据检索 getter 错误
- visual-studio - 使用 Start without Debugging 运行 Web 应用程序时,Visual Studio 可以检测 http 请求并自动重建吗?
- node.js - 从 Heroku 向 mLab 调用 api 时拓扑被破坏
- spring - Spring中带有maven的多模块项目
- java - JNI 中的 ReleaseStringUTFChars 导致崩溃 (SIGSEGV)