如何在房间数据库中使用多项选择

How to use Multiple Selection with Room Database

我怎样才能 link 交易到会员,就像 link 一个交易 ID 到多个会员 ID?

我有一个 activity 来创建新交易,在那个 activity 我输入交易的名称并有一个按钮可以插入。单击该按钮后,我想查看成员列表。

然后我要选择我要link的会员进行交易。通过单击每个成员,它应该会在我选择的成员旁边显示一个勾号或其他内容,或者它应该将单击的成员设置为不同的颜色。

那么交易应该与我选择的所有 linked 成员一起插入。

我现在是这样做的,我只是创建了一个新交易,点击它,用所选的交易开始一个新的 activity,然后在工具栏中我点击一个按钮开始另一个activity 我应该可以通过交易选择我想要 link 的成员。

是否可以在新交易activity中直接选择我要link的会员进行交易?或者是否可以进行新交易,当我单击按钮保存新交易时,它会将记录插入数据库并在插入后直接在 activity 中选择成员 link 到交易开始?

关于我的删除方法:我在 onSwipe 方法中实现了该方法。我怎样才能点击多个交易,它们有一个勾号或不同的颜色,然后同时删除它们?

我可以点击一个按钮(例如在工具栏中)删除,然后选择多个成员,点击一个"confirm delete"按钮,让确认屏幕出现(但还没有删除),然后接受确认屏幕,删除它们?

Class 交易:

@Entity(tableName = "transaction_table")
public class Transaction {

@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "TransactionID")
private long id;

@ColumnInfo(name = "Transaction Name")
private String transactionName;

@ColumnInfo(name = "Transaction Balance")
private double balance;

public double getBalance() {
    return balance;
}

public void setBalance(double balance) {
    this.balance = balance;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getTransactionName() {
    return transactionName;
}

public void setTransactionName(String transactionName) {
    this.transactionName = transactionName;
}

public Transaction(String transactionName, double balance) {
    this.transactionName = transactionName;
    this.balance = balance;
}

}

Class 会员:

@Entity(tableName = "member_table")
public class Member {


@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "MemberID")
private long id;

@ColumnInfo(name = "First Name")
private String firstname;

@ColumnInfo(name = "Surname")
private String surname;

@ColumnInfo(name = "Balance")
private double balance;

public String getFirstname() {
    return firstname;
}

public void setFirstname(String firstname) {
    this.firstname = firstname;
}

public String getSurname() {
    return surname;
}

public void setSurname(String surname) {
    this.surname = surname;
}

public double getBalance() {
    return balance;
}

public void setBalance(double balance) {
    this.balance = balance;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public Member(String firstname, String surname) {
    this.firstname = firstname;
    this.surname = surname;
    this.balance = 0;
}

}

Class 交易主要 Activity:

public class TransactionMainActivity extends AppCompatActivity implements TransactionListAdapter.TransactionClickListener {

private TransactionViewModel mTransactionViewModel;
private List<Transaction> mTransaction;

public static final int NEW_TRANSACTION_ACTIVITY_REQUEST_CODE = 1;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.transaction_activity);
    Toolbar toolbar = findViewById(R.id.toolbar_TransactionMainActivity);
    setSupportActionBar(toolbar);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setTitle(R.string.Transaction);
    }

    FloatingActionButton fab = findViewById(R.id.fab_TransactionMainActivity);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(TransactionMainActivity.this, NewTransactionActivity.class);
            startActivityForResult(intent, NEW_TRANSACTION_ACTIVITY_REQUEST_CODE);
        }
    });

    RecyclerView recyclerView = findViewById(R.id.RecyclerViewCard_Transaction);
    final TransactionListAdapter adapter = new TransactionListAdapter(this);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    mTransactionViewModel = ViewModelProviders.of(this).get(TransactionViewModel.class);

    mTransactionViewModel.getAllTransactions().observe(this, new Observer<List<Transaction>>() {
        @Override
        public void onChanged(@Nullable List<Transaction> transactions) {
            mTransaction = transactions;
            adapter.setTransaction(transactions);
        }
    });

    ItemTouchHelper helper = new ItemTouchHelper(
            new ItemTouchHelper.SimpleCallback(0,
                    ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
                @Override
                public boolean onMove(RecyclerView recyclerView,
                                      RecyclerView.ViewHolder viewHolder,
                                      RecyclerView.ViewHolder target) {
                    return false;
                }

                @Override
                public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                    int position = viewHolder.getAdapterPosition();
                    Transaction myTransaction = adapter.getTransactionAtPosition(position);
                    Toast.makeText(TransactionMainActivity.this,
                            getString(R.string.TransactionDeleted) + " " +
                                    myTransaction.getTransactionName(), Toast.LENGTH_LONG).show();

                    mTransactionViewModel.delete(myTransaction);
                }
            });
    helper.attachToRecyclerView(recyclerView);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.MainMenuToolbarSearch:

        case R.id.MainMenuToolbarAdd:

        case R.id.MainMenuToolbarDelete:

    }
    return super.onOptionsItemSelected(item);
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == NEW_TRANSACTION_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
        Transaction transaction = new Transaction(data.getStringExtra(NewTransactionActivity.EXTRA_REPLY), data.getDoubleExtra(NewTransactionActivity.EXTRA_REPLY2, -1));
        mTransactionViewModel.insert(transaction);
    } else

    {
        Toast.makeText(
                getApplicationContext(),
                R.string.transaction_not_saved,
                Toast.LENGTH_LONG).show();
    }
}

Class 新交易 Activity:

public class NewTransactionActivity extends AppCompatActivity {

public static final String EXTRA_REPLY = "com.example.android.transactionlistsql.REPLY";
public static final String EXTRA_REPLY2 = "com.example.android.transactionlistsql.REPLY2";

private EditText mEditTextTransaction;
private EditText mEditTextTransaction2;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.newtransaction_activity);
    mEditTextTransaction = findViewById(R.id.NewTransactionName);
    mEditTextTransaction2 = findViewById(R.id.NewTransactionBalance);
    mEditTextTransaction2.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
    mEditTextTransaction2.setText("0");
    final Button button = findViewById(R.id.NewTransactionButtonSave);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent replyIntent = new Intent();
            if (TextUtils.isEmpty(mEditTextTransaction.getText())){
                Toast.makeText(getApplicationContext(), R.string.TransactionNameMissing, Toast.LENGTH_LONG).show();
                return;
            }
            else if (TextUtils.isEmpty(mEditTextTransaction2.getText())){
                mEditTextTransaction2.setText("0");
            }
            else {                 
                String newtransactionname = mEditTextTransaction.getText().toString();
                double newtransactionbalance = (Double.parseDouble(mEditTextTransaction2.getText().toString()));
                replyIntent.putExtra(EXTRA_REPLY, newtransactionname);
                replyIntent.putExtra(EXTRA_REPLY2, newtransactionbalance);
                setResult(RESULT_OK, replyIntent);
            }
            finish();
        }
    });
}
}

我的 AsyncTask 插入方法:

    private static class insertAsyncTask extends AsyncTask<Transaction, Void, Void> {

    private TransactionDao mAsyncTaskDao;

    insertAsyncTask(TransactionDao dao) {
        mAsyncTaskDao = dao;
    }

    @Override
    protected Void doInBackground(final Transaction... params) {
        mAsyncTaskDao.insert(params[0]);
        return null;
    }
}

标记为错误的行是这一行:mAsyncTaskDao.insert(params[0]);

错误:

07-11 03:10:49.003 16307-16508/com.example.mainbuchhaltung E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #4

Process: com.example.mainbuchhaltung, PID: 16307

java.lang.RuntimeException: An error occurred while executing doInBackground()

    at android.os.AsyncTask.done(AsyncTask.java:309)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)
 Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)
#################################################################
Error Code : 787 (SQLITE_CONSTRAINT_FOEIGNKEY)
Caused By : Abort due to constraint violation.
    (FOREIGN KEY constraint failed (code 787))
#################################################################
    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:915)
    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
    at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
    at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:50)
    at android.arch.persistence.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
    at com.example.mainbuchhaltung.Transaction.TransactionDao_Impl.insert(TransactionDao_Impl.java:96)
    at com.example.mainbuchhaltung.Transaction.TransactionRepository$insertAsyncTask.doInBackground(TransactionRepository.java:64)
    at com.example.mainbuchhaltung.Transaction.TransactionRepository$insertAsyncTask.doInBackground(TransactionRepository.java:54)
    at android.os.AsyncTask.call(AsyncTask.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        ... 4 more

创建事务和成员实体之间的关系,如前所述

然后,一旦您获得交易数据(交易名称和金额),您就必须将数据传递给 MemberList activity,例如 here

现在,在您的会员列表屏幕中完成您的选择后,请遵循以下过程:
假设您在字符串中有成员 ID。

String memberIds = "12,18,25,27,30";

现在您必须创建所有成员 ID 分开的交易实体对象,并将其插入交易的 table 中,如下所示。

    String[] memberArray = memberIds.split(",", memberIds.length());
            for(String memberId : memberArray){
                // transactionName & transactionAmount which you received in the bundle from add transaction activity
                Transaction objTransaction = new Transaction(transactionName, transactionAmount); 
                objTransaction.setMemberId(Long.parseLong(memberId));
                // Insert data into your database
                mTransactionViewModel.insert(objTransaction);
            }

它将为 "transaction_table" table 中的每个 memberId 创建一个单独的条目,具有一对一的关系。

您可以通过执行上述查询来获取交易数据