在 RoomLibrary 中创建两个表之间的关系

Create a relationship between two tables in RoomLibrary

我有两个 classes,分别叫做 Transaction 和 Person。

交易Class:

@Entity(tableName = "Transaction")
public class Transaction {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private int traderID;
    private int amount;
    private long transactionDate;
    private long dateOfRegistration;
    private String about;
    private long time;
    private String from;
    private String transactionType;
    private long transactionNum;
    private String description;

//Getter and Setter

人Class:

@Entity(tableName = "Person")
public class Person {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String name;
    private long TransactionId;

//Getter and Setter

我阅读了 Google 文档;但是他们看起来很混乱。

我希望这两个 class 通过交易 class 中的 TraderId 和个人 class 中的 TransactionId 连接。

Is this a one to one relationship?

它是一对多的,即一个交易可以被很多人引用。

  • 对于 one-one 关系,您还可以使用 table 交易和个人关系。
  • 也许您想要一个事务引用一个人。
  • 也许你希望一个交易能够有很多人并且一个人可以有很多交易,在这种情况下你会想要一个 Many-Many 关系,在这种情况下你会有一个中间 table(associative/reference/mapping table(同一事物的所有名称))。这样的 table 将有一个交易列和一个人列。

Do I have to build a Dao for each class?

Dao 可以合而为一 class 或分布在 classes.

但是,如果您对每个实体使用 Dao class,那么您很可能想要使用关系,那么您可能会有额外的 Dao classes 来处理关系。

也就是说,您很可能希望与此人一起获得交易。在这种情况下,您将拥有一个同时具有 Person 和 Transaction 的 POJO,因此您可能还有另一个 class 与 Daos。


所以连同你的交易和个人 classes 你可以有 :-

PersonDao

@Dao
interface PersonDao {
    @Insert
    long insert(Person person);
    @Query("SELECT * FROM Person")
    List<Person> getAllPersons();
    @Query("SELECT * FROM Person WHERE id=:personId")
    Person getPersonById(long personId);
}

对于 TransactionDao 也是如此

或者你可以 AllDao

@Dao
abstract class AllDao {

    /* Abstract Class so need to define methods as abstract, but can have non abstract classes */

    @Insert
    abstract long insert(Transaction transaction);
    @Query("SELECT * FROM `Transaction`")
    abstract List<Transaction> getAllTransactions();
    @Query("SELECT * FROM `Transaction` WHERE id=:transactionId")
    abstract Transaction getTransactionById(long transactionId);


    @Insert
    abstract long insert(Person person);
    @Query("SELECT * FROM Person")
    abstract List<Person> getAllPersons();
    @Query("SELECT * FROM Person WHERE id=:personId")
    abstract Person getPersonById(long personId);

} 
  • 注意上面是抽象的class而不是接口。 abstract classes 更灵活一些。

当然,如前所述,您很可能希望获得一个人及其交易,这样您就可以拥有一个 POJO PersonWithTransaction,例如:-

class PersonWithTransaction {

    @Embedded
    Person person;
    @Relation(
            entity = Transaction.class,
            parentColumn = "id",
            entityColumn = "id"
    )
    Transaction transaction;
}

可能使用 PersonWithTransactionDao class 例如:-

@Dao
interface PersonWithTransactionDao {
    @Query("SELECT * FROM Person")
    List<PersonWithTransaction> getAllPersonsWithTransaction();
    @Query("SELECT * FROM Person WHERE id=:personId")
    PersonWithTransaction getPersonWithTransactionByPersonId(long personId);
}
  • 您可能没有插入物。更新或删除,只是查询。
  • 当然以上可以在其他道中

您可能还会发现能够与相关人员进行交易很有用,例如TransactionWithPersons POJO

class TransactionWithPersons {
    @Embedded
    Transaction transaction;
    @Relation(
            entity = Person.class,
            parentColumn = "id",
            entityColumn = "id"
    )
    List<Person> persons;
}
  • 请注意,从理论上讲,交易可以有很多人,那么您就有一个人列表。由于一个人只有 1 个交易,因此 PersonWithTransaction 中不需要列表。但是,@Relation 通常与列表一起使用。

您可能还希望考虑实施参照完整性。那就是 children(Person 是一个 child to Transaction)或者从未被孤立。

按照目前的情况,您可以添加一个 child 和一个不存在的事务 ID,SQLite 也不会抱怨。但是,如果您尝试获取 non-existant 交易(例如使用 getPersonWithTransactionById 查询),那么您将遇到无法检索交易的问题。

您可以定义规则以确保在添加人员时交易存在。您使用 ForeignKeys 来定义此类规则(约束)。所以 Person 可能是:-

@Entity(tableName = "Person",
        /* Defining Foreign Key constraints (rules) enforces referential integrity - Optional */
        foreignKeys = {
                @ForeignKey(
                        entity = Transaction.class,
                        parentColumns = "id",
                        childColumns = "id",
                        /* Optional Define onDelete and onUpdate can be useful
                            e.g. if a Transaction is deleted then all the Persons
                            are deleted that reference/relate to the Transaction are deleted

                            onUpdate is less useful but if the Transaction id is changed then
                            all the Persons that referenced the Transaction will be changed
                            to reflect the update id
                         */
                        onDelete = ForeignKey.CASCADE,
                        onUpdate = ForeignKey.CASCADE
                )
        }
)
public class Person {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String name;
    private long TransactionId;

....