sqlite Android Room非空列

7z5jn7bk  于 2022-11-14  发布在  SQLite
关注(0)|答案(1)|浏览(327)

我在使用Android RoomNOT NULL列时遇到一些问题。我已经在使用@android.support.annotation.NonNull注解,但它不能像预期的那样工作。问题如下:
我有一个随着时间推移而建立起来的数据结构。这意味着构造函数不会构建最终示例。但是一些在数据库中必须具有NOT NULL约束的字段不会在构造函数中初始化。因此,在一段时间内,它们将具有null值。但Android Studio似乎并不喜欢它。到处都是警告Not-null fields must be initialized
有没有其他注解可以用来代替上面提到的注解,以便NOT NULL约束应用于数据库列,而不是应用于在Java代码中定义的字段?
我认为下面的例子更好地描述了这个问题:
我有一个表transaction和一个列amount,其中有一个NOT NULL约束。在我的代码中构造新的transaction时,我还没有可用的数量。我想稍后再分配它。但这并不意味着此字段在数据库中应该是NULL‘。
那么,在这种情况下,最好的解决方案是什么?

xxls0lw8

xxls0lw81#

如果您使用@NonNull注解,那么正如您已经发现的,该值在任何级别都不能为空。也就是说,该注解不是Room注解,而是Android注解。
对于Room,它通过检查用@Entity注解的类来确定列类型和约束,如果它们在通过@数据库注解的Entities参数定义的实体列表中。
对于NOT NULL约束,则适用一些规则。

  • 如果字段/成员变量的类型是Java基元,因为Java基元不能为空,则隐含并因此应用非空约束。
  • 如果字段/成员变量的类型是对象(例如Long而不是long),则除非使用构造函数,否则不存在隐式NOT NULL。
  • 如果字段/成员变量是整型(int、Integer、Long Long...)并使用@PrimaryKey对其进行注解,然后使用便利性@Insert方法来迎合,
  • 在基元的情况下,0值是跳过的值(未指定值),从而生成,这是SQLite的一项功能。
  • 对于对象,表示空值(整数、长整型...)用于跳过并由此生成的值。

举例来说,请考虑:

@Entity
class Transaction {
    @PrimaryKey
    Long id=null;
    long timestamp;
    Long alt_timestamp;
    double amount;
    Double alt_amount;
    ....

当使用扩展RoomDatabase的适当@Database注解类编译时,会生成以下SQL:-

CREATE TABLE IF NOT EXISTS `Transaction` (`id` INTEGER, `timestamp` INTEGER NOT NULL, `alt_timestamp` INTEGER, `amount` REAL NOT NULL, `alt_amount` REAL, PRIMARY KEY(`id`))
  • 可以看到,原语的列(时间戳和数量)编码了NOT NULL约束,而基于对象的列(ALT_TIMESTAMP和ALT_AMOUNT)的NOT NULL约束没有编码。
  • 当使用@数据库注解编译项目时,会生成Java代码。代码可以从Java中的Android视图中找到(生成),类将与注解为@数据库但后缀为**_Impll**的类相同。

例如,如果

@NonNull 
Long alt_timestamp;

则SQL更改为包括非空约束,例如

.... `alt_timestamp` INTEGER NOT NULL` ....

这些都是强加的规则。
那么,作为对的响应,我是否可以使用其他注解来代替上面提到的注解,以便将NOT NULL约束应用于数据库列,而不是应用于我的Java代码中定义的字段?

不是。

但是,您可以记住NOT NULL约束应用于数据库中的列,拥有允许NULL的构造函数。或许可以考虑以下可能适合的做法:

@Entity
class Transaction {
    @PrimaryKey
    Long id=null;
    long timestamp;
    @NonNull
    Long alt_timestamp;
    double amount;
    Double alt_amount;

    Transaction(){}

    @Ignore
    Transaction (Long id, Long timestamp, Long alt_timestamp, Double amount, Double alt_amount) {
        this.id = id;
        if (timestamp==null) timestamp=0L; /* effectively the default value is 0 (could be otherwise to suit) */
        this.timestamp = timestamp; 
        this.alt_timestamp = alt_timestamp; /* can be null BUT if alt_timestamp is @NOTNULL annotated then NOT NULL constraint conflict */
        if (amount==null) amount=0.0D;
        this.amount=amount;
        this.alt_amount=alt_amount;
    }
}
  • @Ignore注解告诉Room不要使用此构造函数,因此它在创建事务对象时将始终使用默认构造函数。

相关问题