【问题标题】:Create a relationship between two tables in RoomLibrary在 RoomLibrary 中创建两个表之间的关系
【发布时间】:2021-12-25 16:47:00
【问题描述】:

我有两个类,称为 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
  • 我希望这两个类通过 TraderId 在 Person 类中的 Transaction 类和 TransactionId。
  • 这是一对一的关系吗?
  • 我必须为每个班级建立一个道吗?

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

【问题讨论】:

    标签: android database android-room relationship dao


    【解决方案1】:

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

    这是一对一的关系吗?

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

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

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

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

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

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


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

    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);
    
    } 
    
    • 请注意,上面是一个抽象类而不是一个接口。抽象类更灵活一些。

    当然,如前所述,您很可能想要获取 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 通常与 List 一起使用。

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

    就目前而言,您可以添加一个事务 id 不存在的子级,SQLite 不会抱怨。但是,如果您尝试获取不存在的事务(例如使用 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;
    
    ....
    

    【讨论】:

    • 非常感谢。这解决了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多