android - 使用带有 Android 的 Room 使用 UUID 作为主键

标签 android android-room

我需要将我的 Android 移动应用程序与云中的 Multi-Tenancy 数据库同步。我认为最好的方法是使用 UUID 作为表的主键。我刚开始使用 Room 并且想知道我可以在哪里/如何做到这一点,并且正在寻找 1)关于将 UUID 用作 Room 的 PK 的意见和 2)我将在哪里实现这个(在模型中初始化 id 列,因为这是使用@NonNull 的唯一方法)?
更新
我使用过 INT,但我不相信这是正确的方法。我看到了 example来自显示正在使用 uuid 的 android 开发者网站。当然会帮助我的云同步程序,但会牺牲速度和空间。我正在考虑一种混合方法,其中 INT 用于 PK,但 UUID 作为附加字段。这样我就不必为 FK 复制每个 UUID。我做了一些建模,看起来混合方法将是完整 UUID 方法大小的 50%(INT 只有 25%)。
有没有人在同样的问题上苦苦挣扎?您是否选择了一个方向(UUID、INT 或混合)并且您后悔了还是效果很好?

最佳答案

  • 您必须使用 UUID 而不是 int 作为主键的原因有很多。例如,您的应用程序是一个分布式应用程序,就像许多人使用许多设备编辑一个文档一样,您将记录每个人的编辑日志以获取版本控制功能。如果您的应用程序是集中式的(大多数情况下),最好使用 int,或者从服务器请求主键(可以是 int、long 或其他)。如果您必须使用 UUID,请使用它。否则 int 或 long 是更好的选择。
  • 最后附上一个使用UUID作为android Room主键的例子。
  • UUID 存储空间和计算速度不应该是首要考虑的,除非你遇到过这些问题(不需要过度优化)。例如:一张图片的存储空间可能在1MB左右,UUID以String的形式保存在数据库中,采用utf-8格式,最多144 Byte(int为4 Byte),约为1/7000的一张照片。在服务器端,不推荐使用 UUID 作为主键,因为服务器同时服务上万用户,同时查询的次数很多。手机CPU虽然远弱于服务器CPU,但一次只为一个用户服务。同样,在必须使用 UUID 的场景下,也无需提前考虑优化问题。

  • 书类
    @Entity(tableName = "books")
    public class Book{
    @PrimaryKey
    @NonNull
    private UUID id;
    private String title;
    private Date date;
    
    public Book() {
        this.id = UUID.randomUUID();
        date = new Date();
    }
    
    public UUID getId() {
        return id;
    }
    
    public void setId(UUID id) {
        this.id = id;
    }
    
    public String getTitle() {
        return title;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public Date getDate() {
        return date;
    }
    
    public void setDate(Date date) {
        this.date = date;
    }
    
    }
    
    应用数据库类
    @Database(entities = {Book.class}, version = 1, exportSchema = false)
    @TypeConverters({UUIDConverter.class, DateConverter.class})
    public abstract class AppDatabase extends RoomDatabase {
        private static AppDatabase INSTANCE;
        private static final String DATABASE_NAME = "BookDatabase";
    
        public abstract BookDao bookDao();
    
        public static void init(Context context) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME).build();
            }
        }
    
        public static AppDatabase getINSTANCE() {
            if (INSTANCE == null) throw new IllegalStateException("init in MyApplication.class");
            return INSTANCE;
        }
    }
    
    转换器:转换器将 sqlite 不支持的 uuid 或其他格式转换为支持类型。
    编辑:来自Version 2.4.0-alpha05存在 UUID 的默认转换器,它使用字节数组而不是字符串。链接 change这对于迁移很方便。
    public class UUIDConverter {
    
        @TypeConverter
        public static String fromUUID(UUID uuid) {
            return uuid.toString();
        }
    
        @TypeConverter
        public static UUID uuidFromString(String string) {
            return UUID.fromString(string);
        }
    }
    
    public class DateConverter {
    
        @TypeConverter
        public static long timestampFromDate(Date date) {
            return date.getTime();
        }
    
        @TypeConverter
        public static Date dateFromTimestamp(long timestamp) {
            return new Date(timestamp);
        }
    }
    

    关于android - 使用带有 Android 的 Room 使用 UUID 作为主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59572749/

    相关文章:

    Android Room DB - 在查询中使用另一个类的静态变量

    android - 推送通知kotlin

    android - 如何正确关闭和重新打开房间数据库

    Android Room 数据库 DAO 调试日志

    java - 房间类型转换器不工作

    android - 无法在后台线程上调用 observeForever

    android - 'res' 中的证书 - 它安全吗?

    android - 从卫报开放平台获取作者姓名

    android - 将文件复制到另一个包文件夹(root,su)

    JSON 对象的 Java 表示