【发布时间】:2023-02-04 05:09:29
【问题描述】:
这是我上一个的延续,但我终于想通了(摆脱了重复问题)。
Android Room Relationship duplicating information
客户表
@Entity(tableName = "customer_table")
public class Customer {
@ColumnInfo(name = "Customer_Serial", index = true)
@PrimaryKey
private int customerSerial;
@ColumnInfo(name = "Customer_Sort", index = true)
private String customerSort;
@ColumnInfo(name = "Customer_Name")
private String customerName;
public Customer(int customerSerial, String customerName) {
this.customerSerial = customerSerial;
this.customerName = customerName;
this.customerSort = String.format(Locale.ENGLISH, "%d-%d", new Date().getTime(), customerSerial);
}
}
发票表
@Entity(tableName = "invoice_table")
public class Invoice {
@ColumnInfo(name = "Invoice_Number", index = true)
@PrimaryKey
private int invoiceNumber;
@ColumnInfo(name = "Customer_Serial")
private int customerSerial;
@ColumnInfo(name = "Invoice_Sort", index = true)
private String invoiceSort;
@ColumnInfo(name = "Delivery_Status")
private int deliveryStatus;
public Invoice(int invoiceNumber, int customerSerial) {
this.invoiceNumber = invoiceNumber;
this.customerSerial = customerSerial;
this.invoiceSort = String.format(Locale.ENGLISH, "%d-%d", new Date().getTime(), invoiceNumber)
}
public void setDeliveryStatus(int deliveryStatus) {
this.deliveryStatus = deliveryStatus;
}
public int getDeliveryStatus() { return deliveryStatus; }
}
客户发票关系
public class CustomerInvoice {
@Embedded public Customer customer;
@Relation(
parentColumn = "Customer_Serial",
entityColumn = "Customer_Serial"
entity = Invoice.class
)
public List<Invoice> invoices;
}
道
public abstract class InvoiceDao {
@Transaction
@Query("SELECT * FROM invoice_table " +
"JOIN customer_table " +
"ON invoice_table.Debtor_Ser_No = customer_table.Customer_Serial " +
"WHERE invoice_table.Delivery_Status = :deliveryStatus " +
"GROUP BY customer_table.Customer_Serial " +
"ORDER BY customer_table.Customer_Sort, invoice_table.Invoice_Sort")
abstract public LiveData<List<CustomerInvoices>> getCustomerInvoices(int deliveryStatus);
abstract public void insert(Invoice... invoice);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract public void insertCustomer(Customer... customer);
}
视图模型public LiveData<List> getCustomerInvoices(int deliveryStatus) { return dao.getCustomerInvoices(); }
测试
Invoice invoice1 = new Invoice(1234, 1);
Invoice invoice2 = new Invoice(1235, 1);
Invoice invoice3 = new Invoice(2468, 2);
Invoice invoice4 = new Invoice(2469, 2);
Customer customer1 = new Customer(1, "Customer 1");
Customer customer2 = new Customer(2, "Customer 2");
dao.insertCustomer(customer1);
dao.insertCustomer(customer2);
dao.insert(invoice1);
dao.insert(invoice2);
dao.insert(invoice3);
dao.insert(invoice4);
invoice1.setDeliveryStatus(0);
invoice2.setDeliveryStatus(0);
invoice3.setDeliveryStatus(0);
invoice4.setDeliveryStatus(0);
viewModel.getCustomerInvoices2(0).observe(getViewLifeCycleOwner(), list -> { ... });
如果我调试观察者的输出,它会正确返回 2 个客户,每个客户有 2 张发票。
但是,如果我这样做
测试2
invoice1.setDeliveryStatus(1);
viewModel.getCustomerInvoices2(1).observe(getViewLifeCycleOwner(), list -> { ... });
它返回 1 个客户和 2 张发票,而不是 1 个客户和 1 张发票,因为该客户的第二张发票的交付状态仍然为 0。
我意识到问题出在 CustomerInvoice 关系中,它忽略了 invoice_table 本身的 where 子句(它仍然完美地执行 customer where 子句)。
但是,我似乎无法全神贯注地解决它。
我已经在 Google 上搜索了很长一段时间,我知道这是因为它基本上只是在做“让客户至少有一张交货状态正确的发票”,然后它在做“为这个客户获取所有发票” ,几乎所有我能找到的东西都提供了根本不涉及 LiveData 的基本示例,我需要它才能使用 LiveData。
我试图让它工作的众多尝试之一是在视图模型本身中做大量的跑腿工作。
道
@Query("SELECT * FROM customer_table " +
"JOIN invoice_table " +
"ON customer_table.Customer_Serial = invoice_table.Debtor_Ser_No " +
"WHERE invoice_table.Delivery_Status = :deliveryStatus " +
"GROUP BY customer_table.Customer_Serial ORDER BY customer_table.Customer_Sort")
abstract public Maybe<List<Customer>> getCustomersByDeliveryStatus(int deliveryStatus);
@Query("SELECT * FROM invoice_table " +
"WHERE invoice_table.Debtor_Ser_No = :debtorSerial " +
"AND invoice_table.Delivery_Status = :deliveryStatus " +
"ORDER BY invoice_table.Invoice_Sort")
abstract public Single<List<Invoice>> getCustomerInvoicesByDeliveryStatus(int debtorSerial, int deliveryStatus);
视图模型
public LiveData<List<Map<Customer, List<Invoice>>>> getCustomerInvoices2(int deliveryStatus) {
MutableLiveData<List<Map<Customer, List<Invoice>>>> liveCustomerInvoices = new MutableLiveData<>();
List<Map<Customer, List<Invoice>>> listCustomerInvoices = new ArrayList<>();
mInvoiceDao
.getCustomersByDeliveryStatus(deliveryStatus)
.subscribeOn(Schedulers.io())
.subscribe(
(customers) -> {
for (Customer customer : customers) {
mInvoiceDao.getCustomerInvoicesByDeliveryStatus(
customer.getCustomerSerial(),
deliveryStatus
).subscribeOn(Schedulers.io())
.subscribe(
(invoices) -> {
listCustomerInvoices.add(Collections.singletonMap(customer, invoices));
}
);
}
liveCustomerInvoices.postValue(listCustomerInvoices);
}, throwable -> Log.e("Error", "Error")
);
return liveCustomerInvoices;
}
虽然它确实有效(在不同程度上,LiveData 不会立即更新,所以有时它什么都不显示,有时它只显示一件事,直到我刷新显示),而我的 recyclerview 显示了我需要它显示的内容,它不维护基于必须维护的“Customer_Sort”和“Invoice_Sort”的订单。
我也明白为什么,这是因为“地图”不能保证顺序。
【问题讨论】:
标签: android android-room android-livedata rx-java3