讨论如何使用嵌套集合为实体建模

2017-10-22 android android-database android-room android-orm

我尝试重构一些代码,并移动一些体系结构以使用体系结构组件中的Room Database。

我有这样的对象,我经常使用它,从缓存中获取它。 这里看起来像:

public class LocationEvents {

private Map<NexoIdentifier, Date> mDeviceFirstSeenDates;

private ArrayDeque<LocationGeoEvent> mGeoEvents;
private ArrayDeque<LocationRSSIEvent> mRSSIEvents;
private Map<NexoIdentifier, ScoredLocationEvent> mHighestScores;

///Some methods

}

我想用这种结构对数据库建模。 因此,将存在诸如LocationGeoEvent,LocationRSSIEvent,ScoredLocationEvent之类的实体。

他们看起来像这样:

public class LocationGeoEvent {

private double mLongitude;
private double mLatitude;
private double mAccuracy;
private Date mTimestamp;
}

public class LocationRSSIEvent {

private int mRSSI;
private NexoIdentifier mNexoIdentifier;
private Date mTimestamp;
}

public class ScoredLocationEvent {

private float mScore;
private NexoIdentifier mNexoIdentifier;
private LocationRSSIEvent mLocationRSSIEvent;
private LocationGeoEvent mLocationGeoEvent;
private Date mScoreCalculatedTime;
private boolean mSent;
private boolean mPreviousSent;
}

NexoIdentifier是一个简单的POJO:

class NexoIdentifier {
abstract val partialSerialID: String
abstract val id: String
abstract val countryAndManufacturer: String
}

那么如何使用Room建立关系?甚至可以一次创建LocationEvent实体吗?因此,例如,我希望能够使用嵌套在其中的所有此列表来获取LocationEvent。也许还有另一种方法可以做到这一点? 还不知道如何准确地将LocationEvents中的这两个地图(DeviceFirstSeenDates和HighestScores)建模为两个相互关联的单独实体?但是到底如何呢?在这个示例中,我将非常感谢您的帮助,我真的很困

更新

@Entity(tableName = "location_events")
data class LocationEvents(
    @PrimaryKey(autoGenerate = true)
                 val id: Long = 0,
    @Embedded(prefix = "device") val mDeviceFirstSeenDates: Map<NexoIdentifier, Date> = HashMap(),
    @Embedded(prefix = "events") val mGeoEvents: ArrayDeque<LocationGeoEvent> = ArrayDeque(),
    val mRSSIEvents: ArrayDeque<LocationRSSIEvent> = ArrayDeque(),
    val mHighestScores: Map<NexoIdentifier, ScoredLocationEvent> = HashMap()
                 ) {
constructor() : this(0L, hashMapOf<NexoIdentifier, Date>(),
        ArrayDeque(), ArrayDeque(), hashMapOf<NexoIdentifier, ScoredLocationEvent>()
)

}

错误:错误:实体和Pojos必须具有可用的公共构造函数。您可以有一个空的构造函数或一个其参数与字段匹配的构造函数(按名称和类型)。

Answers

您可以使用嵌入式。如果变量名相同,则要使用前缀。

例:

public class LocationEvents {

@Embedded(prefix="device") private Map<NexoIdentifier, Date> mDeviceFirstSeenDates;
@Embedded(prefix="events") private ArrayDeque<LocationGeoEvent> mGeoEvents;
private ArrayDeque<LocationRSSIEvent> mRSSIEvents;
private Map<NexoIdentifier, ScoredLocationEvent> mHighestScores;
}

或者您为此编写一个Converter。

例:

public class DBConverters {
@TypeConverter
public static mapToString(Map<NexoIdentifier, Date value) {
    return value == null ? null : Gson.toJson(value);
}

@TypeConverter
public static Map<NexoIdentifier, Date> fromMap(String value) {
    return value == null ? null : Gson.fromJson(value, ...);
}
}

并在数据库类中注释您的Converter

@TypeConverters(DBConverters::class)
abstract class YourDb : RoomDatabase() { }

更新(代码更新后):

该警告表示您至少需要一个可用的构造函数。为了解决这个问题并仍然允许“数据”类,您需要使用ignore注释,并注意您没有任何可为空的值。

@Ignore constructor() : this(0L, hashMapOf<NexoIdentifier, Date>(),
        ArrayDeque(), ArrayDeque(), hashMapOf<NexoIdentifier, ScoredLocationEvent>()

这将确保Room使用您的类标题中使用的构造函数。

房间本身没有“真实的” 关系 ,但是您可以创建一个包含关系的“虚拟类”。 Room支持ForeignKey,通过它可以定义关系被更新或删除时的行为。请注意,只能将嵌入式用于其他类。如果有像HashMap这样的未知类型,您将要编写一个转换器。

Related