如何在 Android 中将数据与房间数据库合并

How to merge data with Room Database in Android

我有两个不同的 class,其中一个 class 包含其他 class 的列表。

下面有一个新发票 class,它包含一个发票项目列表。

@Entity(tableName = "invoices")
public class NewInvoice implements Parcelable {

@NonNull
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "transaction_id")
public int transaction_id;
@ColumnInfo(name = "invoiceNo")
public String invoiceNo;
@ColumnInfo(name = "contactId")
public String contactId;
@ColumnInfo(name = "currencyCode")
public String currencyCode;
@ColumnInfo(name = "description")
public String description;
@ColumnInfo(name = "creationDate")
public long creationDate;
@ColumnInfo(name = "invoiceDate")
public long invoiceDate;
@ColumnInfo(name = "dueDate")
public long dueDate;
@ColumnInfo(name = "shipmentDate")
public long shipmentDate;
@ColumnInfo(name = "invoiceDiscount")
public double invoiceDiscount;
@ColumnInfo(name = "discountType")
public byte discountType;
@ColumnInfo(name = "invoiceAmount")
public double invoiceAmount;
@ColumnInfo(name = "balance")
public double balance;
@ColumnInfo(name = "taxIncluded")
public boolean taxIncluded;
@ColumnInfo(name = "status")
public int status;
@ColumnInfo(name = "type")
public int type;

@Ignore
public List<InvoiceItem> invoiceItems;


public NewInvoice() {
}

下面是 InvoiceItem class

@Entity(tableName = "invoice_items")
public class InvoiceItem implements Parcelable {
@NonNull
@PrimaryKey()
@ColumnInfo(name = "itemId")
private String itemId;
@ColumnInfo(name = "invoiceId")
private String invoiceId;
@ColumnInfo(name = "unitPrice")
private double unitPrice;
@ColumnInfo(name = "quantity")
private double quantity;
@ColumnInfo(name = "inventoryId")
private String inventoryId;
@ColumnInfo(name = "taxIncluded")
private int taxIncluded;
@ColumnInfo(name = "taxRate")
private double taxRate;
@ColumnInfo(name = "discountRate")
private double discountRate;
@ColumnInfo(name = "discountType")
private int discountType;

public InvoiceItem() {
}

我正在使用 Room 数据库。目前,我先查询NewInvoice记录,然后查询与NewInvoice记录相关的InvoiceItem记录,并将InvoiceItem对象添加到NewInvoice obcejt的invoiceItems数组列表中。

有没有办法查询包含 InvoiceItem 记录的 NewInvoice 记录。

如果要获取包含 InvoiceItem 记录的 NewInvoice 记录,则需要此查询:

SELECT invoiceNo
  FROM invoices
 WHERE invoiceNo IN (
           SELECT invoiceId
             FROM invoice_items
       );

如果 'invoices' 中的 'invoiceNo' 等于 'invoice_items' 中的 'invoiceId'。

如果您不熟悉子查询:https://www.sqlitetutorial.net/sqlite-subquery/

通常,这将通过让两个实体具有 NewInvoice(然后不需要 invoiceItems 列表但因为它被忽略可以保留)然后第三个 POJO class 嵌入 NewInvoice@Embedded 注释,并具有 InvoiceItem 的列表,并用 @Relation.

注释

例如

class NewInvoiceWithListOfRelatedInvoiceItems {
    @Embedded
    private NewInvoice newInvoice;
    @Relation(
            entity = InvoiceItem.class,
            parentColumn = "invoiceNo",
            entityColumn = "invoiceId"
    )
    private List<InvoiceItem> invoiceItemList;

    public NewInvoice getNewInvoice() {
        return newInvoice;
    }

    public void setNewInvoice(NewInvoice newInvoice) {
        this.newInvoice = newInvoice;
    }

    public List<InvoiceItem> getInvoiceItemList() {
        return invoiceItemList;
    }

    public void setInvoiceItemList(List<InvoiceItem> invoiceItemList) {
        this.invoiceItemList = invoiceItemList;
    }
}

然后你可以有一个 @Query 例如(对于单个 NewInvoice)

@Transaction
@Query("SELECT * FROM invoices WHERE invoiceNo=:invoiceNo")
NewInvoiceWithListOfRelatedInvoiceItems getInvoiceWithItems(String invoiceNo);

或者对于所有新发票然后:-

@Transaction
@Query("SELECT * FROM invoices")
List<NewInvoiceWithListOfRelatedInvoiceItems> getAllInvoicesWithItems();

或者,如果您将 @Dao 设为抽象 class,则仅使用您拥有的 classes(POJO那么不需要)。通过具有以下 Dao 的例如:-

@Dao
abstract class NewInvoiceDao {

    @Query("SELECT * FROM invoice_items WHERE invoiceId=:invoiceNo")
    abstract List<InvoiceItem> getInvoiceItemsForANewInvoice(String invoiceNo);

    @Query("SELECT * FROM invoices WHERE invoiceNo=:invoiceNo")
    abstract NewInvoice getNewInvoiceByInvoiceNo(String invoiceNo);

    @Transaction
    @Query("")
    NewInvoice getNewInvoiceWithInvoiceItems(String invoiceNo) {
        NewInvoice rv = getNewInvoiceByInvoiceNo(invoiceNo);
        rv.setInvoiceItems(getInvoiceItemsForANewInvoice(invoiceNo));
        return rv;
    }
}

额外

在任何一种情况下,建议在 invoiceNoinvoiceId 列上建立索引(假设这是用于关系的列)。

因此,对于 NewInvoice,您可以将 @Entity 注释设为 :-

@Entity(tableName = "invoices", indices = {@Index(value = "invoiceNo", unique = true)})

对于 InvoiceIteminvoiceId 列的 @ColumnInfo 为:-

@ColumnInfo(name = "invoiceId", index = true)
private String invoiceId;