首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用UUID实现主键--使用Android机房

用UUID实现主键--使用Android机房
EN

Stack Overflow用户
提问于 2020-01-03 03:14:18
回答 2查看 7.7K关注 0票数 10

我需要将我的Android移动应用程序与云中的多租户数据库同步。我认为最好的方法是使用UUID作为表的主键。我刚刚开始使用Room,并且想知道我可以在哪里/如何这样做,并且正在寻找关于使用UUID作为一个带有Room和2)的PK的意见(在初始化id列的模型中,因为这是使用@NonNull的唯一方法)?

更新

我使用了INTs,但我不相信这是正确的方法。我在android站点上看到了一个示例,它显示了正在使用的uuid。当然会帮助我的云同步例程,但牺牲速度和空间。我正在考虑一种混合方法,将INT用于PKs,但UUID作为附加字段使用。这样,我就不必为FKs复制每个UUID。我做了一些建模,看起来混合方法将是整个UUID方法的50% ( INT只有25%大)。

有没有人为同样的问题而挣扎过?你选择了一个方向(UUID,INT,或者混合),你后悔了吗?还是说它运行得很好?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-23 09:27:38

  1. 您必须使用UUID而不是int作为主要key.For示例的原因有几个,您的应用程序是一个分布式应用程序,就像许多人使用许多设备一样,编辑一个文档,并且您将记录每个人的编辑日志以实现版本控制功能。如果您的应用程序是集中式的(大多数情况下),最好使用int,或者向服务器请求主键(可以是int、long或其他什么)。如果你必须使用UUID,那就使用它。否则,int或long是更好的选择。
  2. 最后,我将附上一个使用UUID作为android主键的示例。
  3. UUID存储空间和计算速度不应该是首要考虑因素,除非您遇到了这些问题(不需要过度优化)。例如:图片的存储空间可能约为1MB,UUID以字符串的形式以utf-8格式保存在数据库中,高达144 Byte (int为4 Byte),约为图片的1/7000。在服务器端,不建议将UUID作为主键,因为服务器同时为成千上万的用户服务,同时有许多查询。尽管移动电话CPU比服务器CPU弱得多,但它一次只能为一个用户服务。同样,在必须使用UUID的场景中,没有必要预先考虑优化问题。

Book.class

代码语言:javascript
复制
@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;
}

}

AppDatabase.class

代码语言:javascript
复制
@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或其他格式转换为支持类型。编辑:从版本2.4.0-字母05默认转换器UUID存在,这是使用字节数组,而不是字符串。链接变化,可以方便地进行迁移。

代码语言:javascript
复制
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);
    }
}
票数 3
EN

Stack Overflow用户

发布于 2020-01-03 05:16:13

UUID比使用rowid的别名更难,效率更低。您只需使用column_name INTEGER PRIMARY KEY来表示列,列是rowid的别名。

当值未给定时,SQLite将生成一个整数值。值可以达到9223372036854775807 (您也可以使用负值,这样就可以发生2次)。

使用rowid可以达到2倍的速度。

您可以指定一个值,它必须是一个整数。

问题是云中的统一性。如果应用程序没有分配价值,那么就没有问题。

如果您希望具有随机性,那么SQlite将生成一个唯一的随机值,如果不使用自动生成(只要@PrimaryKey的实体长度不长),并且使用rowid 9223372036854775807 (当到达SQLite时,查找随机值)。

如果正和负随机性想要,那么以及添加行与9223372036854775807,添加一个负值。

这就是你简单地在房间里做的方法

实体类

代码语言:javascript
复制
@Entity
public class RandomId {

    @PrimaryKey
    Long randomId;
    String name;

    public RandomId(){}

    public Long getRandomId() {
        return randomId;
    }

    public void setRandomId(Long randomId) {
        this.randomId = randomId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

刀样

代码语言:javascript
复制
@Dao
public interface RandomIdDao {

    @Insert
    long insert(RandomId randomId);

    @Query("SELECT * FROM randomid ORDER BY name")
    List<RandomId> getAll();
}

@Database(version = 1,entities = {RandomId.class})
public abstract class RandomIdDatabase extends RoomDatabase {

    abstract RandomIdDao randomIdDao();
}

活动类

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {

    RandomIdDatabase randomIdDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        randomIdDatabase = Room.databaseBuilder(this,RandomIdDatabase.class,"randomiddb")
                .allowMainThreadQueries()
                .addCallback(new RoomDatabase.Callback() {
                    @Override
                    public void onCreate(@NonNull SupportSQLiteDatabase db) {
                        super.onCreate(db);
                        /* SETUP FOR positive and negative randomids */
                        ContentValues cv = new ContentValues();
                        cv.put("randomId",9223372036854775807L);
                        db.insert("RandomID", OnConflictStrategy.IGNORE,cv);
                        cv.clear();
                        cv.put("RandomId",-9223372036854775808L);
                        db.insert("RandomID", OnConflictStrategy.IGNORE,cv);
                    }
                })
                .build();
        randomIdDatabase.getOpenHelper().getWritableDatabase().beginTransaction();
        RandomId r = new RandomId();
        for (int i = 0; i < 1000; i++) {
            r.setRandomId(null);
            r.setName("name" + String.valueOf(i));
            randomIdDatabase.randomIdDao().insert(r);
        }
        randomIdDatabase.getOpenHelper().getWritableDatabase().setTransactionSuccessful();
        randomIdDatabase.getOpenHelper().getWritableDatabase().endTransaction();
        List<RandomId> randomIds = randomIdDatabase.randomIdDao().getAll();
        for (RandomId randomId : randomIds) {
            Log.d("IDDATA","name is " + randomId.getName() + " ID is " + randomId.getRandomId());
        }
    }
}

跑得像

D/IDDATA: name is null ID是-9223372036854775808 D/IDDATA: name is null ID为9223372036854775807 D/IDDATA: name is name0 ID为41072993476813590 D/IDDATA: name is name1 ID为22838362508669948 D/IDDATA: name is name10 ID为3903077050951194 D/IDDATA: name10 name100 ID为94821181770704090341/IDDATA:名称为name101 ID为80607588718587575D/IDDATA:名称为name102 ID为320463188743981564 D/IDDATA: name103 ID为3777087074644/ name104 :IDDATA为2846060871858587525D/IDDATA:名称为name1023597159533635558763 D/IDDATA:名称为name107 ID为3199952401843656135 D/IDDATA:名称为name108 ID为47449628201566105 D/IDDATA:名称为name109 ID为48604112123921960369 D/IDDATA:名称为name11 ID为1162315037045532434 D/IDDATA:名称为name110 ID为28071787194055346105 D/IDDATA:名称为name111 ID为3643686187723794393 D/IDDATA:名称为name111 ID为45516415748625814 D/IDDATA:名称为name1132244323676217441072 D/IDDATA: name118 ID为911318293674111436 D/IDDATA:名称为name119 ID为14349150093930897 D/IDDATA:名称为name12 ID为2661856341619735016 .

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59572749

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档