Android Room 插入所有问题

Posted

技术标签:

【中文标题】Android Room 插入所有问题【英文标题】:Android Room insertAll issues 【发布时间】:2018-02-05 23:16:25 【问题描述】:

我开始使用 android Room,但遇到了一些问题。

我有 7 个订单的 ArrayList,当我调用 insertAll(List orders) 数据库中只插入了 4 个订单。

如何调试插入查询以找到阻塞的内容?

谢谢

【问题讨论】:

你的订单表有主键吗?如果是这样,当数据存在冲突时,您选择了哪个选项? 您好,感谢您的帮助。我确实有一个主键,我选择了 OnConflictStrategy.REPLACE 所以它正在执行 7 次插入,但是当我插入所有订单时,getAll() 方法只返回其中的 4 个...... 这很奇怪......它必须是一个简单的查询,比如“SELECT * FROM orders”,你能把你的 DAO 和你的实体/pojo 放在问题中吗? @Dao public interface OrderDao @Insert(onConflict = OnConflictStrategy.REPLACE) public long insertOrder(Order order); @Query("SELECT * FROM orders") List getAll(); @Entity(tableName = TABLE_NAME) public class Order public static final String TABLE_NAME = "orders"; @PrimaryKey 私有 int id; @SerializedName("order_number") @ColumnInfo(name = "order_number") private String orderNumber; // 调用 (int i = 0; i myOrders = mDb.getOrderDao().getAll(); 【参考方案1】:

Room 完成的调用不是同步的,所以可能在您执行时

List<Order> myOrders = mDb.getOrderDao().getAll()

它仍在插入订单。

试试这个

@Dao 
public interface OrderDao  
    @Insert(onConflict = OnConflictStrategy.REPLACE) 
    public long insertOrder(Order order); 

    @Insert(onConflict = OnConflictStrategy.REPLACE) 
    void insertAllOrders(List<Order> order); 

    @Query("SELECT * FROM orders") 
    List<Order> getAll(); 
 

@Entity(tableName = TABLE_NAME) 
public class Order  
   public static final String TABLE_NAME = "orders"; 
   @PrimaryKey (autoGenerate = true)
   private int id; 
   @SerializedName("order_number") 
   @ColumnInfo(name = "order_number") 
   private String orderNumber; 
 

// Call 
mDb.getOrderDao().insertAllOrders(orders);
Log.d(TAG, "inserted all");

Executor executor = Executors.newSingleThreadExecutor();

executor.execute(new Runnable() 
        @Override
        public void run() 

             List<Order> myOrders = mDb.getOrderDao().getAll();
             Log.d(TAG, "Orders nr = " + myOrders.size()); 
        
);

【讨论】:

谢谢它的工作!如果我必须链接多个查询,那么正确的方法是什么? 这是个好问题。我对 Room 还是很陌生,但我认为如果您使用 executor 执行调用,那么它应该可以工作,但我不能保证。但我认为您永远不需要对数据库执行超过两次连续调用 这不是真的。房间插入是同步的,因此当 insertAll 返回时,将插入所有数据。而且,即使您尝试从另一个线程读取该数据,您也永远不会收到部分数据。 insert(List) 会自动放入事务中,因此任何其他并行查询都可以在所有这些被插入之前或在所有这些被插入之后看到 db。 @Yigit:请写下您的评论作为答案,以便人们可以轻松看到。但是,由于 insert(List) 是在一个事务中完成的,这个答案如何解决 Jerome 遇到的问题。 我在了解如何解决问题时遇到问题。如果insertAllOrders()是异步的,那么在调用insertAll()之后创建newSingleThreadExecutor()如何保持单线程执行? InsertAll() 可以在完成之前返回。您不必至少将insertAllOrders()getAll() 都放在execute() 块内吗?【参考方案2】:

必须添加 OnConflict 属性。

@Insert(onConflict = OnConflictStrategy.REPLACE) 

【讨论】:

以上是关于Android Room 插入所有问题的主要内容,如果未能解决你的问题,请参考以下文章

Android Room:使用 Room 插入关系实体

在不触发发射的情况下插入 Android Room 表?

Android Room - 通过自动生成获取新插入行的 id

如何从 api 获取数据并将数据插入 Android Studio 中的 ROOM(数据库)?

Android Room - 使用自动生成获取新插入行的 id - MVVM 版本

Android Room Database 应用程序崩溃但未显示任何错误