会议室:LiveData一对多关系

时间:2019-06-11 08:43:44

标签: java android

我有一个包含两个表的数据库。

第一名:queue_incoming

+---------------+
|  column_name  | pk   
+---------------+
|id             | 1
|api_id         | 0
|driver         | 0
|vehicle_number | 0
+---------------+

第二张桌子:包

+------------------+
|  column_name     | pk   
+------------------+
|id                | 1
|api_id            | 0
|queue_incoming_id | 0
|driver            | 0
|vehicle_number    | 0
+------------------+

两个表之间的关系是一个queue_incoming有很多包。 queue_incoming.id = bag.queue_incoming_id

问题是,我需要将每个queue_incoming记录中的bag的所有记录合并到一个列表中。

到目前为止,这是代码。 非常感谢。

实体:QueueIncomingEntity.java

@Entity(tableName = "queue_incoming")
public class QueueIncomingEntity {

    @PrimaryKey(autoGenerate = true)
    private Long id;

    @ColumnInfo(name = "api_id")
    private Integer ApiId;

    @ColumnInfo(name = "driver")
    private String driver;

    @ColumnInfo(name = "vehicle_number")
    private String vehicleNumber;

    @ColumnInfo(name = "date_unique_number")
    private String dateUniqueNumber;

    @ColumnInfo(name = "unique_number")
    private String uniqueNumber;

    @ColumnInfo(name = "message")
    private String message;

    @ColumnInfo(name = "status")
    private String status;

    @Ignore
    private List<BagEntity> bagEntities; // handle all bags in each queue

    // Constructor
    public QueueIncomingEntity(String driver, String vehicleNumber, String dateUniqueNumber, String uniqueNumber, String message, String status) {
        this.driver = driver;
        this.vehicleNumber = vehicleNumber;
        this.dateUniqueNumber = dateUniqueNumber;
        this.uniqueNumber = uniqueNumber;
        this.message = message;
        this.status = status;
    }

    // Getter Setter

}

DAO:QueueIncomingDao.java

@Dao
public interface QueueIncomingDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long insert(QueueIncomingEntity queueIncomingEntity);

    @Update
    void update(QueueIncomingEntity queueIncomingEntity);

    @Delete
    void delete(QueueIncomingEntity queueIncomingEntity);

    @Query("DELETE FROM queue_incoming")
    void deleteAll();

    @Query("SELECT * FROM queue_incoming WHERE id =:id")
    QueueIncomingEntity findById(long id);

    @Query("SELECT * FROM queue_incoming ORDER BY id DESC")
    LiveData<List<QueueIncomingEntity>> getAll();

    // This is the problem, how to pass this , or how to related this on LiveData
    @Query("SELECT " +
            "bag.id as id," +
            "bag.api_id as apiId," +
            "bag.bag_number as bagNumber," +
            "bag.lot_number as lotNumber," +
            "bag.consignee_name as consigneeName," +
            "bag.allocation_consignee as allocationConsignee," +
            "bag.nett_weight as nettWeight," +
            "bag.gross_weight as grossWeight " +
            "FROM queue_incoming " +
            "LEFT JOIN bag bag ON bag.queue_incoming_id = queue_incoming.id WHERE queue_incoming.id = :id")
    List<QueueIncoming> getAllJoinBags(long id);

    // Inner class to handle method getAllJoinBags
    class QueueIncoming {
        public Long id;
        public Integer apiId;
        public Integer bagNumber;
        public String lotNumber;
        public String consigneeName;
        public String allocationConsignee;
        public Integer nettWeight;
        public Integer grossWeight;

        // Getter Setter
    }

}

存储库

public class QueueIncomingRepository {

    private QueueIncomingDao queueIncomingDao;
    private BagDao bagDao;
    private Context context;
    private ArrayList<BagLotNumberModel> bagLotNumbers;
    private LiveData<List<QueueIncomingEntity>> listLiveData;

    // constructor
    public QueueIncomingRepository(Application application) {

        AppDatabase database = AppDatabase.getInstance(application);

        queueIncomingDao = database.queueIncomingDao();
        listLiveData = queueIncomingDao.getAll();
    }

     // a lot of crud code

     // Handling LiveData
    public LiveData<List<QueueIncomingEntity>> getAll() {
        return listLiveData;
    }
}

ViewModel:QueueIncomingViewModel.java

public class QueueIncomingViewModel extends AndroidViewModel {

    private QueueIncomingRepository queueIncomingRepository;
    private LiveData<List<QueueIncomingEntity>> listLiveData;

    /**
     * Create constructor matching super
     */
    public QueueIncomingViewModel(@NonNull Application application) {
        super(application);
        queueIncomingRepository = new QueueIncomingRepository(application);
        listLiveData = queueIncomingRepository.getAll();
    }

    public void insert(QueueIncomingEntity queueIncomingEntity) {
        queueIncomingRepository.insert(queueIncomingEntity);
    }

    public void update(QueueIncomingEntity queueIncomingEntity) {
        queueIncomingRepository.update(queueIncomingEntity);
    }

    public void delete(QueueIncomingEntity queueIncomingEntity) {
        queueIncomingRepository.delete(queueIncomingEntity);
    }

    public void deleteAll() {
        queueIncomingRepository.deleteAll();
    }

    public LiveData<List<QueueIncomingEntity>> getListLiveData() {
        return listLiveData;
    }
}

活动:AntamQueueIncomingRoomActivity.java

public class AntamQueueIncomingRoomActivity extends AppCompatActivity {

    public static final int ADD_QUEUE_INCOMING = 1;
    public static final int EDIT_QUEUE_INCOMING = 2;
    public static final int EDIT_QUEUE_INCOMING_BAGS = 3;
    public static final int RE_UPLOAD = 4;

    private QueueIncomingViewModel queueIncomingViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_antam_incoming_room);

        RecyclerView recyclerView = findViewById(R.id.recycler_view_antam_queue_incoming);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);

        QueueIncomingAdapter adapter = new QueueIncomingAdapter();
        recyclerView.setAdapter(adapter);

        queueIncomingViewModel = ViewModelProviders.of(this).get(QueueIncomingViewModel.class);
        queueIncomingViewModel.getListLiveData().observe(this, queueIncomingEntities -> {

            adapter.submitList(queueIncomingEntities);

        });

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(view -> {
            Intent intent = new Intent(getApplicationContext(), AntamAddEditQueueIncomingRoomActivity.class);
            startActivityForResult(intent, ADD_QUEUE_INCOMING);
        });

        //handling item click on row adapter
        adapter.setOnItemClickListener(new QueueIncomingAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(QueueIncomingEntity queueIncomingEntity) {

                String[] options = {"1. Update Master Incoming", "2. Update Detail Bags", "3. Re-Upload"};
                AlertDialog.Builder builder = new AlertDialog.Builder(AntamQueueIncomingRoomActivity.this);
                builder.setTitle("Menu: " + queueIncomingEntity.getDriver() + " # " + queueIncomingEntity.getVehicleNumber());
                builder.setItems(options, (dialog, which) -> {
                    switch (which) {
                        case 2:
                            Intent intent2 = new Intent(AntamQueueIncomingRoomActivity.this, AntamDialogReUploadIncomingActivity.class);

                            // Data Master
                            intent2.putExtra(AntamDialogReUploadIncomingActivity.EXTRA_ID, Long.valueOf(queueIncomingEntity.getId()));
                            intent2.putExtra(AntamDialogReUploadIncomingActivity.EXTRA_API_ID, queueIncomingEntity.getApiId());

                            // Get Data Detail bags, how ?
                            // Get and passing All bags into new ActivityForResult

                            startActivityForResult(intent2, RE_UPLOAD);
                            break;
                        default:
                            break;
                    }
                });
                builder.show();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ADD_QUEUE_INCOMING && resultCode == RESULT_OK) {

            // insert


        } else if (requestCode == EDIT_QUEUE_INCOMING && resultCode == RESULT_OK) {

            Long id = Long.valueOf(data.getLongExtra(AntamAddEditQueueIncomingRoomActivity.EXTRA_ID, -1));

            // Update
            queueIncomingEntity.setId(id);
            queueIncomingViewModel.update(queueIncomingEntity);

            Toast.makeText(this, data.getStringExtra(AntamAddEditQueueIncomingRoomActivity.EXTRA_DRIVER) + " is successfully updated", Toast.LENGTH_SHORT).show();
        } else if (requestCode == RE_UPLOAD) {

        }
    }
}

BagEntity.java

我之前已经声明过

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.PrimaryKey;

@Entity(
        tableName = "bag",
        foreignKeys = {
                @ForeignKey(
                        entity = QueueIncomingEntity.class,
                        parentColumns = "id",
                        childColumns = "queue_incoming_id",
                        onDelete = ForeignKey.CASCADE
                ),

                @ForeignKey(
                        entity = QueueContainerStuffingEntity.class,
                        parentColumns = "id",
                        childColumns = "queue_container_stuffing_id"
                )
        }
)
public class BagEntity {

    @PrimaryKey(autoGenerate = true)
    private Long id;

    @ColumnInfo(name = "api_id")
    private Long ApiId;

    @ColumnInfo(name = "queue_incoming_id", index = true)
    private Long queueIncomingId;

    @ColumnInfo(name = "queue_container_stuffing_id", index = true)
    private Long queueContainerStuffingId;

    @ColumnInfo(name = "bag_number")
    private Integer bagNumber;

    @ColumnInfo(name = "lot_number")
    private String lotNumber;

    @ColumnInfo(name = "consignee_name")
    private String consigneeName;

    @ColumnInfo(name = "allocation_consignee")
    private String allocationConsignee;

    @ColumnInfo(name = "nett_weight")
    private Integer nettWeight;

    @ColumnInfo(name = "gross_weight")
    private Integer grossWeight;


    public BagEntity(Long ApiId, Integer bagNumber, String lotNumber, String consigneeName, String allocationConsignee, Integer nettWeight, Integer grossWeight, Long queueIncomingId, Long queueContainerStuffingId) {
        this.ApiId = ApiId;
        this.bagNumber = bagNumber;
        this.lotNumber = lotNumber;
        this.consigneeName = consigneeName;
        this.allocationConsignee = allocationConsignee;
        this.nettWeight = nettWeight;
        this.grossWeight = grossWeight;
        this.queueIncomingId = queueIncomingId;
        this.queueContainerStuffingId = queueContainerStuffingId;
    }

    // Getter Setter


}

1 个答案:

答案 0 :(得分:1)

我认为您错过了BagEntity.java中的 @ForeignKey @ForeignKey 将连接两个表,因此将触发任何表更新实时数据。

第二件事是您的输出列表不是实时数据类型。您必须在LiveData<List<QueueIncoming>>

之类的查询中更新输出列表

更新:您可以在viewModel中进行尝试   //首先声明

private final MediatorLiveData<List<QueueIncoming>> mObservableProducts;

在dao调用之后的构造函数中

mObservableProducts.addSource(products, new Observer<List<UserEntity>>() {
            @Override
            public void onChanged(@Nullable List<QueueIncoming> outputDaoList) {
                mObservableProducts.postValue(outputDaoList);
            }
        });

并在您的视图模型中编写一个可以从活动中观察到的方法

public LiveData<List<QueueIncoming>> getAllList() {
        return mObservableProducts;
    }