首页 > 解决方案 > 在 RoomLibrary 中创建两个表之间的关系

问题描述

我有两个类,称为 Transaction 和 Person。

交易类:

@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

人物类:

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

//Getter and Setter

我阅读了谷歌文档;但它们似乎令人困惑。

标签: androiddatabaseandroid-roomrelationshipdao

解决方案


我希望通过 Transaction 类中的 TraderId 和 Person 类中的 TransactionId 连接这两个类。

这是一对一的关系吗?

,它是一对多,即一个事务可以被许多人引用。

  • 对于一对一的关系,您不妨拥有一张带有 Transaction 和 Person 的表。
  • 也许有一个引用一个人的事务是你想要的。
  • 也许你希望一个事务能够有很多人并且一个人可以有很多事务,在这种情况下你会想要一个多对多关系,在这种情况下你会有一个中间表(关联/引用/映射表(同一事物的所有名称))。这样的表将有一个用于事务的列和一个用于人员的列。

我必须为每个班级建立一个道吗?

Dao 可以全部在一个类中,也可以分布在多个类中。

但是,如果您为每个实体使用 Dao 类,您很可能想要使用关系,那么您可能需要额外的 Dao 类来处理关系。

那就是您很可能希望与 Person 一起获得 Transaction。在这种情况下,您将拥有一个包含 Person 和 Transaction 的 POJO,因此您可能还有另一个带有 Daos 的类。


因此,您可以拥有 Transaction 和 Person 类:-

人道

@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);

} 
  • 请注意,上面是一个抽象类而不是一个接口。抽象类更灵活一些。

当然,如前所述,您很可能想要获取 Person 及其 Transaction,因此您可以拥有 POJO PersonWithTransaction例如:-

class PersonWithTransaction {

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

也许使用PersonWithTransactionDao类,例如:-

@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 与列表一起使用。

您可能还希望考虑强制执行参照完整性。那就是孩子(Person is a child to Transaction)或者永远不会成为孤儿。

就目前而言,您可以添加一个具有不存在的事务 id 的子级,并且 SQLite 不会抱怨。但是,如果您尝试获取不存在的事务(例如使用 getPersonWithTransactionById 查询),那么您将遇到无法检索事务的问题。

您可以定义规则以确保添加人员时事务存在。您使用 ForeignKeys 来定义这样的规则(约束)。所以可能是:-

@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;

....

推荐阅读