如何使用嵌套集合为Entity建模

时间:2017-10-21 16:14:48

标签: android android-database android-room android-orm

我尝试重构一些代码并移动几个架构以使用架构组件中的Room数据库。

我有这样的对象,我经常使用它从缓存中获取它。 这就是它的样子:

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
}

那我如何利用房间建立关系呢?甚至可以将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必须具有可用的公共构造函数。您可以拥有一个空构造函数或其参数与字段匹配的构造函数(按名称和类型)。

1 个答案:

答案 0 :(得分:4)

您可以使用Embedded。如果您使用相同的变量名称,则需要使用前缀。

示例:

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;
}

或者你为此写了一个转换器。

示例:

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 constructor() : this(0L, hashMapOf<NexoIdentifier, Date>(),
        ArrayDeque(), ArrayDeque(), hashMapOf<NexoIdentifier, ScoredLocationEvent>()

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

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