本文介绍了如何存储 List<Object>在房间数据库中?(我在使用 DAO 查询检索列表时遇到问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 Device 对象存储在 Room 数据库中,但在检索作为浮点数列表的属性 (temp_values) 之一时遇到问题.我遵循了here上的其他建议,说明您需要一个类型转换器,所以我在这里展示了这一点.当我尝试编译时出现此错误:

I am storing Device objects in a Room database and I'm having a problem with retrieving one of the attributes (temp_values) that is a list of floats. I've followed other advice found on here that says you need a type converter so I've shown that here. When I try to compile I get this error:

"警告:查询返回一些列 [temp_values],这些列不是由 java.lang.Float 使用.您可以在字段来指定映射.您可以通过以下方式抑制此警告用@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH).返回的列查询:temp_values.java.lang.Float 中的字段:."

问题在于 DAO 中的 getTempValues 查询,如果我将其注释掉,那么一切都可以正常编译.我在 Device 对象、TemperatureListConverter 和我的 DAO 下面包含了.

The issue is with the getTempValues query in the DAO, if I comment this out then everything compiles fine. I've included below the Device object, the TemperatureListConverter, and my DAO.

@Entity(tableName = "devices")
@TypeConverters(TemperatureListConverter.class)
public class Device implements Serializable {

    @PrimaryKey
    @NonNull
    @ColumnInfo(name = "serial_num")
    private String serialNum;

    @ColumnInfo(name = "temp_values")
    @TypeConverters(TemperatureListConverter.class)
    private List<Float> tempValues;

    public Device(String serialNum) {
        this.serialNum = serialNum;
        this.tempValues = new ArrayList<>();
    }

    public String getSerialNum() {
        return serialNum;
    }

    public List<Float> getTempValues() {
        return tempValues;
    }

    public void setTempValues(List<Float> tempValues) {
        this.tempValues = tempValues;
    }
}
public class TemperatureListConverter {

    private static final Gson gson = new Gson();

    @TypeConverter
    public static List<Float> toTempList(String tempValuesString) {
        if (tempValuesString == null) {
            return Collections.emptyList();
        }

        Type type = new TypeToken<List<Float>>() {}.getType();
        return gson.fromJson(tempValuesString, type);
    }

    @TypeConverter
    public static String fromTempList(List<Float> tempValues) {
        return gson.toJson(tempValues);
    }
}
@Dao
@TypeConverters(TemperatureListConverter.class)
public interface DeviceDao {
    @Query("SELECT * FROM devices")
    List<Device> getAllDevices();

    @Query("SELECT * FROM devices WHERE serial_num = :serialNum")
    Device getDevice(String serialNum);

    @Query("SELECT temp_values FROM devices WHERE serial_num = :serialNum")
    List<Float> getTempValues(String serialNum);

    @Query("UPDATE devices SET temp_values = :tempValues WHERE serial_num = :serialNum")
    int setTempValues(String serialNum, List<Float> tempValues);

    @Insert
    void insert(Device... device);

    @Query("DELETE FROM devices WHERE serial_num = :serialNum")
    void deleteBySerial(String serialNum);
}

我在这里添加了我的数据库类.

I've added my database class here.

@Database(entities = {Device.class}, version = 37, exportSchema = false)
@TypeConverters(TemperatureListConverter.class)
public abstract class DeviceDatabase extends RoomDatabase {

    private static final String DB_NAME = "devices_db";
    private static DeviceDatabase deviceDb;

    // simple singleton
    public static DeviceDatabase getDeviceDb(Context context) {
        if (deviceDb == null) {
            deviceDb = Room.databaseBuilder(context, DeviceDatabase.class, DB_NAME)
                    .fallbackToDestructiveMigration()
                    .build();
        }

        return deviceDb;
    }

    public abstract DeviceDao getDeviceDao();

    public void addDevice(final Device device) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    getDeviceDao().insert(device);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void removeDevice(final String serialNum) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    getDeviceDao().deleteBySerial(serialNum);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public Device getDevice(final String serialNum) {
        final Device[] finalDevice = new Device[1];

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    finalDevice[0] = getDeviceDao().getDevice(serialNum);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();

        try {
            thread.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return finalDevice[0];
    }

    public List<Float> getTempValues(final String serialNum) {
        final List<Float> finalTempValues = new ArrayList<>();

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                 finalTempValues.addAll(getDeviceDao().getTempValues(serialNum));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();

        try {
            thread.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return finalTempValues;
    }

    public void setTempValues(final String serialNum, final List<Float>
                                tempValues) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    getDeviceDao().setTempValues(serialNum, tempValues);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

推荐答案

当 Room 处理返回集合类型(在本例中为List)的查询时,它会尝试生成一个实现对于返回表的多行的查询.这是典型用途,如在您的查询中获取所有设备:

When Room processes a query that returns a collection type (List<Float> in this case), it tries to generate an implementation for a query that returns multiple rows of the table. That is the typical use, as in your query to get all devices:

@Query("SELECT * FROM devices")
List<Device> getAllDevices();

当在查询中使用返回集合的 TypeConverter 以生成单行时,您需要给 Room 一个您想要的提示.一种方法是将集合值包装在一个类中:

When a TypeConverter that returns a collection is used in a query intended to yield a single row, you need to give Room a hint of what you want. One way to do that is to wrap the collection value in a class:

public class ListWrapper {
    @ColumnInfo(name = "temp_values")
    List<Float> tempValues;
}

并更改查询以返回包装类:

And change the query to return the wrapper class:

@Query("SELECT temp_values FROM devices WHERE serial_num = :serialNum LIMIT 1")
ListWrapper getTempValues(String serialNum);

我用你发布的代码试过了.它消除了构建错误并似乎生成了所需的实现代码.

I tried this with the code you posted. It eliminates the build error and appears to produce the desired implementation code.

这篇关于如何存储 List<Object>在房间数据库中?(我在使用 DAO 查询检索列表时遇到问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 20:30