【问题标题】:How to automatically set timestamp in room SQLite database?如何在房间 SQLite 数据库中自动设置时间戳?
【发布时间】:2019-12-13 13:53:11
【问题描述】:

我正在尝试让 SQLite 使用 CURRENT_TIMESTAMP 创建自动时间戳。

我冒昧地使用了谷歌的code

// roomVersion = '2.2.2'
@Entity
public class Playlist {
    @PrimaryKey(autoGenerate = true)
    long playlistId;
    String name;
    @Nullable
    String description;
    @ColumnInfo(defaultValue = "normal")
    String category;
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    String createdTime;
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    String lastModifiedTime;
}

@Dao
interface PlaylistDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(playlist: Playlist): Long
}

这转化为 SQLite 语句:

CREATE TABLE `Playlist` (
    `playlistId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
    `name` TEXT, 
    `description` TEXT, 
    `category` TEXT DEFAULT 'normal', 
    `createdTime` TEXT DEFAULT CURRENT_TIMESTAMP, 
    `lastModifiedTime` TEXT DEFAULT CURRENT_TIMESTAMP
)

我确实做了一个插入:

mDb.playListDao().insert(Playlist().apply { name = "Test 1" })

但时间戳始终为 Null。

使用 SQLite 的 DB 浏览器,我添加了另一个条目,在这里我得到了时间戳。

如何在房间中插入没有 Null-Timestamp 的内容?

(信息:createdTime 也始终与 lastModifiedTime 相同。我认为这必须通过 SQLite 中的触发器来完成,但这是一个不同的问题,此处不予讨论)。

【问题讨论】:

  • 可能您的 DAO 代码明确传递了 NULL 而不是跳过列或传递 DEFAULT
  • NOT NULL?
  • 完整代码如上。我没有明确设置值,但对象会。但我需要对象中的字段来创建房间样式的表格。所以:如何不设置Null(“”也一样)。

标签: sqlite android-room


【解决方案1】:

您不需要使用其他类,您可以使用@Query 作为便利@Insert 的替代品。

根据:-

查询方法支持 4 种类型的语句:SELECT、INSERT、UPDATE 和 DELETE。 Query

例如

@Query("INSERT INTO test_table001 (name) VALUES(:name) ")
void insert(String name);

您也不限于将 CURRENT_TIMESTAMP 作为获取当前时间戳的唯一方法,您可以使用嵌入式日期时间函数(如下所示),它可以更有效地存储值,也更灵活,例如您可以使用诸如“+7 天”之类的修饰符来调整当前时间

如果您考虑以下几点:-

@Entity(tableName = "test_table001")
public class TestTable001 {

    @PrimaryKey
    Long id;
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    String dt1;
    @ColumnInfo(defaultValue = "(datetime('now'))")
    String dt2;
    @ColumnInfo(defaultValue = "(strftime('%s','now'))")
    String dt3;
    String name;
}
  • 请注意,效率低下的autogenerate = true 没有被使用,但正如将显示的那样,您仍然可以分配一个 SQLite id (请注意,您必须使用 Long/Integer 类型,而不是 long 或 int)时间>
  • 还要注意获取当前日期时间的其他方法(后者效率更高,因为该值最终将存储为整数(最多 8 个字节)而不是更多字节的字符串)。

以道为:-

@Dao
public interface TestTable001Dao {

    @Insert()
    long insert(TestTable001 testTable001);

    @Query("INSERT INTO test_table001 (name) VALUES(:name) ")
    long insert(String name);

    @Query("SELECT * FROM test_table001")
    List<TestTable001> getAllTestTable001();
}

以及以下要测试/演示的内容:-

public class MainActivity extends AppCompatActivity {

    AppDatabase mRoomDB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRoomDB = Room.databaseBuilder(this,AppDatabase.class,"testdb")
                .allowMainThreadQueries()
                .build();

        TestTable001 tt01 = new TestTable001();
        tt01.setName("tt01");
        mRoomDB.useTestTable001().insert(tt01);
        mRoomDB.useTestTable001().insert("tt02");

        logAllTestTable001();
    }

    private void logAllTestTable001() {
        for (TestTable001 tt: mRoomDB.useTestTable001().getAllTestTable001()) {
            Log.d(
                    "TTINFO",
                    "ID = " + tt.getId() +
                            " Name = " + tt.getName() +
                            " Date1 = " + tt.getDt1() +
                            " Date2 = " + tt.getDt2() +
                            " Date3 = " + tt.getDt3());
        }
    }
}

结果是:-

2019-12-14 03:18:32.569 D/TTINFO: ID = 1 Name = tt01 Date1 = null Date2 = null Date3 = null
2019-12-14 03:18:32.569 D/TTINFO: ID = 2 Name = tt02 Date1 = 2019-12-13 16:18:32 Date2 = 2019-12-13 16:18:32 Date3 = 1576253912

【讨论】:

  • 有趣的方法。在插入查询中需要很多字段,而我目前对所有表都使用“暂停有趣的插入(obj:T):Long”的扩展类。 .allowMainThreadQueries 也 +1,不知道那个。
【解决方案2】:

找到了。没看说明书。

您必须创建一个没有自动设置字段的第二类。

public class NameAndDescription {
   String name;
   String description
}

我认为,这不是一个好主意。 如果您在数据库中有一个自动增量字段,那么当您传递 0 时,它将获得一个自动更新的值。 同样,在传递 null 或 "" 时应使用时间戳的默认值。

【讨论】:

    【解决方案3】:

    我发现最好的解决方案是创建一个抽象的 Dao 来实现插入和更新方法。我没有让默认值起作用(也许我做错了什么)。看看我的回答:How to implement created_at and updated_at column using Room Persistence ORM tools in android

    【讨论】:

      猜你喜欢
      • 2013-01-05
      • 2020-08-28
      • 2020-09-23
      • 2018-05-24
      • 2020-04-05
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多