【问题标题】:How do I prepopulate my Room database?如何预填充我的 Room 数据库?
【发布时间】:2018-07-18 13:10:12
【问题描述】:

这是我第一次尝试使用 Room 数据库,我想用 20 个用户对象预先填充数据库。但是我使用的代码每次运行时都会在现有列表中增加 20 个用户。如何防止它这样做?

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

private static AppDatabase INSTANCE;
public abstract DataExchange dataExchange();

public static AppDatabase getAppDatabase(final Context context){
    if (INSTANCE == null){
        INSTANCE = Room.databaseBuilder(context,
                AppDatabase.class,
                "User_Database")
                .addCallback(new Callback() {
                    @Override
                    public void onCreate(@NonNull final SupportSQLiteDatabase db) {
                        super.onCreate(db);
                        Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
                            @Override
                            public void run() {
                                getAppDatabase(context).dataExchange().insert(User.populate());
                            }
                        });
                    }
                })
                .build();
    }
    return INSTANCE;
}

public static void destroyInstance(){
    INSTANCE = null;
}

这是用户类:

@Entity(tableName = "user_table")
public class User{

public User(String name){
    setName(name);
}

@PrimaryKey(autoGenerate = true)
private int uid;

@ColumnInfo(name = "Username")
private String name;

public String getName() {
    return name;
}

public void setUid(int uid) {
    this.uid = uid;
}

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

public static User[] populate(){
    User[] ar = new User[20];
    for(int i=0; i<20;i++){
        ar[i] = new User("USER "+(i+1));
    }
    return ar;
}
}

另外,我从中获取代码的地方有一个 getInstance(context) 而不是 run() 中的 getAppDatabase(context)。我更改了它,因为在我不知道的 5 个库中找到了 getInstance。

这里是数据交换:

@Dao
public interface DataExchange {

@Query("SELECT * FROM user_table")
List<User> getAll();

@Query("SELECT * FROM user_table where username LIKE  :name ")
User findByName(String name);

@Query("SELECT COUNT(*) from user_table")
int countUsers();

@Update
void update(User user);

@Insert
void insertAll(User... users);

@Delete
void delete(User user);

}

【问题讨论】:

  • 使用 @Entity@Dao ,在实体中应该有一个主键,每个用户都是唯一的
  • @Redman 每个用户都有一个 int 变量和一个 String 值。 int 变量是主键。
  • 当应用程序被杀死并再次打开时,用户的int变量是否相同?
  • 它应该保持不变。不会吗?这就是我使用数据库的原因。
  • 再说一次,你为什么要对我们隐藏 User 类?里面有什么私密的东西不想让我们看到吗?

标签: java android sql android-room


【解决方案1】:

第 1 步:

为您的实体添加主键,建议在您的场景中使用 int。例如:ID 为 1 的用户在您的数据库中是唯一的。

@Entity
public class User {
    @PrimaryKey
    public int id;
}

https://developer.android.com/training/data-storage/room/defining-data

第 2 步:

为 id 变量赋值。我建议通过User类的构造函数来赋值(主要是防止它为0,或者防止你稍后在setter中忘记赋值)

第 3 步:

在你的@Insert 中定义一个冲突策略(在你的 DAO 类中)。当你的数据库试图添加一个 id = 1 的用户时,你希望你的数据库做什么?是否要删除旧用户?直接忽略?

 @Insert(onConflict = OnConflictStrategy.REPLACE)
 public void insertUsers(User... users);

https://developer.android.com/reference/android/arch/persistence/room/Insert

另外,我 100% 确定您在猜测代码。只需查看官方文档即可。

【讨论】:

  • 谢谢。那行得通。一直以来,我一直认为错误仅在 AppDatabase 中。
【解决方案2】:

我建议只复制您使用 DB Browser for SQLite 创建的数据库。这是进行预填充的最简单方法。您只需在您的应用中创建 Assets 文件夹,添加文件夹数据库,然后复制您的数据库。 在您创建数据库的单例类中,只需添加 createFromAsset() 方法,您就有了预填充的数据库。照片在那个链接上。

https://i.stack.imgur.com/Q5o4v.jpg

在这篇文章中也描述得非常好。 https://medium.com/androiddevelopers/packing-the-room-pre-populate-your-database-with-this-one-method-333ae190e680

【讨论】:

    猜你喜欢
    • 2018-06-27
    • 1970-01-01
    • 2019-09-08
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多