0

我试图在java中实现用于持久数据存储的Room。但是我遇到了问题。

在第一次尝试中:

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addUser(UserDetails userDetails);

}

我的数据库.java

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

    public abstract MyDao myDao();
}

上面的应用程序崩溃并出现错误:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
每当我尝试将数据插入数据库时​​。

在第二次尝试中:

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    ListenableFuture<Integer> addUser(UserDetails userDetails);

}

我的数据库.java

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

    public abstract MyDao myDao();
}

将返回类型更改为保持ListenableFuture<Integer>,因为官方文档说要这样做。该应用程序未成功构建并显示以下错误:
error: Not sure how to handle insert method's return type.

所以,我的问题是如何使用带有 java 的 room 正确并成功地将数据插入数据库中。
请帮忙。

4

3 回答 3

0

您基本上是在第一次运行应用程序时创建了数据库,并试图在引发错误的主线程上访问数据库。

当您更改数据库并尝试运行应用程序时,您更改了数据库方案而没有提供到新版本的迁移。

更改数据库的解决方案是,打开设备管理器并删除您的数据库,这会强制系统使用您更新的数据库方案创建数据库的新实例。或者,您可以提供在为已投入生产的应用程序更新数据库方案时所必需的迁移

您尝试从主线程访问数据库的错误的解决方案是,数据库操作需要异步处理并且不允许阻塞主线程。

您需要创建一个访问数据库的线程,使用 kotlin 您可以简单地创建一个协程并将操作作为协程运行。使用 Java,您应该使用 RXJava

于 2021-02-19T00:17:17.423 回答
0
  1. 要在 UI 线程中使用 Room,您需要初始化数据库,如下所示

     database = Room.databaseBuilder(YOUR_CONTEXT, AppDatabase.class, "database")
         .allowMainThreadQueries() //this string need for working in UI thread
         .build();
    

但不建议在生产代码中做

  1. 我从未使用过 Guava,但这里有一份使用 ListenableFuture的指南。

正如 Dominik Wuttke 所说,您可以使用协程或 RxJava 而不是 ListenableFuture 进行异步工作。

于 2021-02-19T00:33:10.887 回答
0

在互联网上徘徊多年后,我知道可以使用以下两种方法编写插入查询:

  1. 使用线程类

操作.java

public class Operations{

    private MyDao myDao;

    public Operations(Context context){
        MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
                .fallbackToDestructiveMigration()
                .build();
        myDao = db.myDao();
    }

    public void insertUser(UserDetails userDetails){
        new Thread{
            @override
            public void run(){
                myDao.addUser(userDetails);
            }
        }.start();
    }

}

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addUser(UserDetails userDetails);

}

我的数据库.java

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

    public abstract MyDao myDao();
}

或者

  1. 使用 ExecutorService 类

操作.java

public class Operations{

    private MyDao myDao;

    public Operations(Context context){
        MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
                .fallbackToDestructiveMigration()
                .build();
        myDao = db.myDao();
    }

    public void insertUser(UserDetails userDetails){
        MyDatabase.databaseWriteExecutor.execute(()->{
               notesDb.notesDao().addNote(note));
           }
    }

}

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addUser(UserDetails userDetails);

}

我的数据库.java

@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
    
    public static final ExecutorService databaseWriteExecutor =
            Executors.newFixedThreadPool(2);

    public abstract MyDao myDao();
}
于 2021-02-24T18:35:36.390 回答